7장 클래스에 대해서

- Fraction Class를 사용해 보자.

Fraction 예제

Fraction.h

#import <Foundation/Foundation.h>


@interface Fraction : NSObject


-(void) print;

-(void) setNumerator: (int)n;

-(void) setDenominator: (int)d;

-(int) numerator;

-(int) denominator;

-(double) convertToNum;


@end

- @interface 를 통해 Fraction Class를 선언한다. 

- 일반적으로 NSObject를 상속 받아 기본적인 속성을 상속받도록 한다. (옵션)

- Fraction Class가 6개의 인스턴스 메서드를 가지고 있음을 선언하였다.


Fraction.m

#import "Fraction.h"


@implementation Fraction

{

    int numerator;

    int denominator;

}


-(void) print

{

    NSLog(@"%i/%i", numerator, denominator);

}

-(void) setNumerator: (int)n

{

    numerator = n;

}

-(void) setDenominator: (int)d

{

    denominator = d;

}

-(int) numerator

{

    return numerator;

}

-(int) denominator

{

    return denominator;

}

-(double) convertToNum

{

    if(denominator != 0){

        return (double) numerator/denominator;

    }else{

        return NAN;

    }

}


@end

- @implementation 에 Fraction Class를 구현함을 알려준다.

- 파란색 부분은 인스턴스 변수를 선언해주는 부분이다.

- 윈도우즈에 설치한 GNUStep에서는 이부분에서 에러가 발생한다. GNUStep에서는 @interface 부분에 선언해 주어야 한다.

- NAN: Not a Number의 약자로 숫자가 아닌 값을 나타낸다. NAN과 계산하는 값은 모두 NAN이 되며 objective-C에서는 isnan()으로 구별 할 수 있다.


main.m

#import <Foundation/Foundation.h>

#import "Fraction.h"


int main(int argc, const char * argv[])

{


    @autoreleasepool {

        

        // insert code here...

        NSLog(@"Hello, World!");

        Fraction *myFraction = [[Fraction alloc] init];        // Fraction 인스턴스화

        [myFraction setNumerator:1];                            // numerator 값 설정

        [myFraction setDenominator:3];                         // denominator 값 설정

        NSLog(@"The value of myFraction is :");

        [myFraction print];

        

    }

    return 0;

}
- GNUStep에서는 @autoreleasepool 역시 동작하지 않는다. 제거하도록 하자.

7.1 자동 생성 접근자(@property 와 @synthesize)

- Objective-2.0  부터는 @property 지시어를 사용하여 인스턴스 변수의 속성을 설정할 수 있다.

- @synthesize는 지시어를 사용하여 @property로 설정된 인스턴스 변수의 getter/setter를 자동으로 생성해 준다.

  (GNUStep에서는 지원하지 않는다.)

- @property의 기본형은 다음과 같다.

@property (attribute[, attribute, ...]) type name;        // 기본형

@property (readwrite, assign) BOOL isProperty;         // readwrite, assign 속성의 인스턴스 변수 선언

@property (nonatomic, retain) UIImage* img;

@property (nonatomic, copy)   NSString* name;


- attribute에 들어갈 수 있는 속성은 다음과 같으며 중복해서 사용할 경우 콤마(,) 로 구분해 준다.

 readwrite (default) 

  설정된 변수의 getter/setter를 모두 설정하여 읽고 쓸 수 있도록 합니다. 

 readonly

  설정된 변수의 getter만을 제공하며 값을 할당 하면 에러가 발생합니다.

 assign(default)

 값을 단순히 할당하는 역활을 한다. 객체 할당의 경우 메모리 누수의 원인이 될 수 있으므로 사용에 주의 하여야 한다.

다음과 같이 setter를 생성 할 것이다.

-(void) setIsProperty: (BOOL)value{

    isProperty = value;

}

 retain

 설정된 변수에 레퍼런스 카운트를 증가 시키고 할당 한다. 이전에 설정되어 있던 변수는 release 된다.  

-(void)setImg:(UIImage*) Newimg {

   if(img != Newimg){

      [img release];

       img = [Newimg retain];

   }

}

 copy

 해당 객체를 복사하여 할당한다. copy 에서 retain을 해주므로 retain은 따로 호출해주지 않으며 대상 객체는  NSCopying 프로토콜을 반드시 구현해야 한다. 

기본적으로 생성되는 코드는 다음과 같을 것이다.

-(void) setName: (NSString*) newName {

   if(name != newName) {

      [name release];

      name = [newName copy];

   }

}

 atomic (default)

 변수를 atomic하게 만들어 thread safe 하도록 동작하게 한다. 기본 설정값으로 설정 되어 있으며 lock, unlock을 반복하는 만큼 성능은 좋지 않다.

 nonatomic

 변수를 non-atomic 하게 만들어 thread safe 하지 않도록 만들어 준다. 필요 없는곳은 제거하여 퍼포먼스를 높여주자.

 getter=getterName

 getter의 이름을 getterName으로 설정한다.

 settet=setterName

 setter의 이름을 setterName으로 설정한다. 


- @property 지시어와 @synthesize를 사용하면 다음과 같이 getter/setter를 자동으로 만들어 준다.

Fraction.h

#import <Foundation/Foundation.h>


@interface Fraction : NSObject


@property int numerator, denominator;     //property로 선언하고 getter/setter를 삭제한다.


-(void) print;

-(double) convertToNum;


@end

Fraction.m

#import "Fraction.h"


@implementation Fraction


@synthesize numerator, denominator;     //synthesize를 통해 자동으로 setter/getter를 생성해준다. 


-(void) print

{

    NSLog(@"%i/%i", numerator, denominator);

}


-(double) convertToNum

{

    if(denominator != 0){

        return (double) numerator/denominator;

    }else{

        return NAN;

    }

}


@end

- @property를 선언하면 @synthesize를 통해 내부에서 사용할 예명을 설정 할 수 있다.

- 일반적으로 @synthesize numerator = _numerator; 와 같이 "_" 를 붙여서 사용한다.

- Xocde 4.4 이후로는 @synthesize를 사용하지 않아도 자동으로 "_"가 붙은 getter/setter를 자동으로 만들어 준다.

- property는 . 연산자를 사용하여 좀 더 쉽게 접근할 수 있다.

myFraction.numerator = 1; 

myFraction.denominator = 3;  


7.2 메서드에 여러 인수 넘겨주기

- 다음과 같이 여러 인수를 받는 메서드를 만들 수 있다.

-(void) setTo: (int)num over: (int)denum;    // 함수를 표현 할때 setTo:over: 와 같이 쓰고 읽는다.

[myFraction setTo:1 over:3]                         // 하나에 함수에 두개의 인수를 넘겼다.

- 여기서 over는 callname으로 옵션 사항으로 없어도 된다.

-(void) setTo:(int)num : (int) denum; 은 같은 함수이다.


7.3 self

- 현재 메서드의 수신자인 객체는 self 키워드로 부를 수 있다.

-(void) add: (Fraction *) f

{

   //  TODO: something

   [self reduce];             // Fraction 객체(현재 자기 클래스이다)의 reduce 함수를 호출한다.

}


Posted by 빨간 양말