Objective-C class의 사용에서 눈여겨 볼만한 점들이 세가지 정도 있었습니다. 바로 Protocol, Category와 NSObject의 poseAsClass입니다.
Protocol은 자바, C#의 interface와 유사하며 선언된 메소드들은 프로토콜을 사용하는 클래스에서 반드시 구현되어야 합니다. 사용하는 이유는 C++의 abstract class와 비슷하지만 Objective-C, 자바, C#과 같이 다중상속을 지원하지 않는 언어에서 다중상속의 단점은 버리고 장점은 취하기 위해서입니다. (이에 관한 자세한 설명은 디자인 패턴에 관한 책이나 deadly diamond of death로 구글 검색에서 찾으실 수 있습니다.)
Category는 서브클래스를 구현하지 않더라도 이미 구현되어 있는 클래스에 새로운 메소드들을 추가할 수 있는 방법을 제공합니다. category의 메소드들은 해당 클래스의 변수와 메소드를 사용할 수 있으며 메소드 이름이 같을 경우에는 오버라이드되니 주의하셔야 합니다. Categtory는 서브클래스를 만드는 것 보다 더 간단한 방법으로 문제를 해결할 수 있습니다.
PoseAsClass는 가장 흥미로운 부분입니다. 짧은 제 영어로 번역하자면 '사칭'이 가까운 것 같습니다. 상위 클래스로 선언되었지만 하위 클래스의 PoseAsClass를 이용하면 그 인스턴스는 하위 클래스로 동작하게 됩니다.
아래의 소스를 실행해 보시면 확인해 보실 수 있습니다.
실행결과는 좌측과 같습니다.
[MyNumberMinus poseAsClass: [MyNumber class]];
이 라인은 MyNumberMinus는 앞으로 MyNumber 클래스로 사칭하고 다닌다는 의미입니다. 그래서 아래의 MyNumber *number = [[MyNumber alloc] init]; 선언은 MyNumberMinus *number = [[MyNumberMinus alloc] init]; 와 동일한 의미로 해석될 수 있습니다. 이 라인을 주석처리하고 빌드 후에 결과를 비교하시면 쉽게 이해하실 수 있습니다.
poseAsClass가 유효하기 위해서는 상위클래스가 생성되기 전에 호출되어야 합니다.
Protocol은 자바, C#의 interface와 유사하며 선언된 메소드들은 프로토콜을 사용하는 클래스에서 반드시 구현되어야 합니다. 사용하는 이유는 C++의 abstract class와 비슷하지만 Objective-C, 자바, C#과 같이 다중상속을 지원하지 않는 언어에서 다중상속의 단점은 버리고 장점은 취하기 위해서입니다. (이에 관한 자세한 설명은 디자인 패턴에 관한 책이나 deadly diamond of death로 구글 검색에서 찾으실 수 있습니다.)
Category는 서브클래스를 구현하지 않더라도 이미 구현되어 있는 클래스에 새로운 메소드들을 추가할 수 있는 방법을 제공합니다. category의 메소드들은 해당 클래스의 변수와 메소드를 사용할 수 있으며 메소드 이름이 같을 경우에는 오버라이드되니 주의하셔야 합니다. Categtory는 서브클래스를 만드는 것 보다 더 간단한 방법으로 문제를 해결할 수 있습니다.
PoseAsClass는 가장 흥미로운 부분입니다. 짧은 제 영어로 번역하자면 '사칭'이 가까운 것 같습니다. 상위 클래스로 선언되었지만 하위 클래스의 PoseAsClass를 이용하면 그 인스턴스는 하위 클래스로 동작하게 됩니다.
아래의 소스를 실행해 보시면 확인해 보실 수 있습니다.
#import <Foundation/Foundation.h>
/** Protocol **/
@protocol MyData
-(void) print;
@end
/** MyNumber class **/
@interface MyNumber: NSObject <MyData>
{
int number;
}
-(void) setNumber: (int)n;
-(void) print;
@end
@implementation MyNumber;
-(void) setNumber: (int)n
{
number = n;
}
-(void) print
{
NSLog(@"MyNumber:print > %d", number);
}
@end
/** Category **/
@interface MyNumber (NewPrint)
-(void) print;
-(void) printPlus;
@end
@implementation MyNumber (NewPrint)
-(void) print
{
NSLog(@"NewPrint:print > %d", number);
}
-(void) printPlus
{
NSLog(@"NewPrint:printPlus > %d", number + 1);
}
@end
/** Posing **/
@interface MyNumberMinus: MyNumber
{
}
-(void) print;
@end
@implementation MyNumberMinus;
-(void) print
{
NSLog(@"MyNumberMinus:print > %d", number - 1);
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
[MyNumberMinus poseAsClass: [MyNumber class]];
MyNumber *number = [[MyNumber alloc] init];
[number setNumber: 5];
[number print];
[number printPlus];
[number release];
[pool release];
return 0;
}
/** Protocol **/
@protocol MyData
-(void) print;
@end
/** MyNumber class **/
@interface MyNumber: NSObject <MyData>
{
int number;
}
-(void) setNumber: (int)n;
-(void) print;
@end
@implementation MyNumber;
-(void) setNumber: (int)n
{
number = n;
}
-(void) print
{
NSLog(@"MyNumber:print > %d", number);
}
@end
/** Category **/
@interface MyNumber (NewPrint)
-(void) print;
-(void) printPlus;
@end
@implementation MyNumber (NewPrint)
-(void) print
{
NSLog(@"NewPrint:print > %d", number);
}
-(void) printPlus
{
NSLog(@"NewPrint:printPlus > %d", number + 1);
}
@end
/** Posing **/
@interface MyNumberMinus: MyNumber
{
}
-(void) print;
@end
@implementation MyNumberMinus;
-(void) print
{
NSLog(@"MyNumberMinus:print > %d", number - 1);
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
[MyNumberMinus poseAsClass: [MyNumber class]];
MyNumber *number = [[MyNumber alloc] init];
[number setNumber: 5];
[number print];
[number printPlus];
[number release];
[pool release];
return 0;
}
실행결과는 좌측과 같습니다.
[MyNumberMinus poseAsClass: [MyNumber class]];
이 라인은 MyNumberMinus는 앞으로 MyNumber 클래스로 사칭하고 다닌다는 의미입니다. 그래서 아래의 MyNumber *number = [[MyNumber alloc] init]; 선언은 MyNumberMinus *number = [[MyNumberMinus alloc] init]; 와 동일한 의미로 해석될 수 있습니다. 이 라인을 주석처리하고 빌드 후에 결과를 비교하시면 쉽게 이해하실 수 있습니다.
poseAsClass가 유효하기 위해서는 상위클래스가 생성되기 전에 호출되어야 합니다.
'Xcode 2 > Objective-C' 카테고리의 다른 글
Objective-C 코딩 스타일 (6) | 2008.09.25 |
---|---|
C/C++ 사용자를 위한 간단한 Objective-C 소개 (17) | 2007.05.14 |