Protocol은 Java의 interface와 같다. 즉 어떤 protocol을 따르는(adopting하는) 클래스는 protocol에서 선언된 모든 메소드들을 구현해야한다.
다음은 object를 copy하는 copyWithZone 메소드가 담긴 NSCopying protocol의 선언과 이것을 adopt하는 클래스의 @interface이다.
@protocol NSCopying
- (id) copyWithZone: (NSZone*) zone;
@end
@interface Car : NSObject <NSCopying> // <NSCopying, NSCoding>과 같이
// 여러개의 protocal을 adopt할 수도 있다.
{
// instance variables...
}
// methods...
// protocol 안에 선언되어 있는 메소드는 따로 다시 선언할 필요 없다.
@end
copyWithZone 메소드의 zone은 할당할 메모리 영역을 나타내는 NSZone 타입의 매개변수이다. object의 copy 메소드를 호출할 경우내부적으로 copyWithZone 메소드로 변환되어 호출된다. 따라서 클래스에 따라 이 copyWithZone 메소드를 구현함으로써 그 클래스에 맞는 올바른 copy 되도록 할 수 있다.
다음은 <NSCopying>을 adopt하여 deep copy가 되도록 하는 Engine, Tire, Car 클래스의 copyWithZone 메소드 구현이다.@interface 부분은 생략하겠다.
@implementation Engine
- (id) copyWithZone: (NSZone*) zone
{
/* allocWithZone 메소드는 NSObject 클래스의 class method로서,
* 해당 클래스의 새로운 객체를 생성한다.
* 즉, 객체 자신이 아닌 [self class]를 사용함으로써
* subclass들 역시 [super copyWithZone]을 호출하여 copy에 사용할 수 있다. */
// Engine은 instance variable을 가지지 않으므로 instance variable의 copy 과정 없이
// 바로 init으로 초기화하면 된다.
Engine* engineCopy = [[[self class] allocWithZone:zone] init];
return engineCopy;
}
@end
@implementation Tire
- (id) copyWithZone: (NSZone*) zone
{
Tire* tireCopy = [[[self class] allocWithZone: zone]
initWithPressure: pressure treadDepth: treadDepth];
return tireCopy;
}
@end
@implementation Car
- (id) copyWithZone: (NSZone*) zone
{
Car *carCopy = [[[self class] allocWithZone: zone] init];
carCopy.name = self.name;
// engineCopy는 copy에 의해 생성된 것이므로 memory management rule에 의하여 release까지 책임을 져야 한다.
// 여기에서는 autorelease를 걸어주었다.
Engine* engineCopy = [[engine copy] autorelease];
carCopy.engine = engineCopy;
int i;
for(i = 0; i < 4; i++)
{
Tire* tireCopy = [[self tireAtIndex: i] copy];
// tire역시 copy로 생성되었으므로 autorelease를 걸어준다.
[tireCopy autorelease];
[carCopy setTire:tireCopy atIndex:i];
}
return carCopy;
}
@end
앞서 id 타입은 어떠한 object도 가리킬 수 있는 generic 타입이라고 설명하였다. 다음과 같이 id에 protocol을 붙여줌으로써 이protocol을 만족하는 object들만을 가리키게 할 수 있다.
- (void) setObjectValue: (id<NSCopying>) obj;
Objective-C 2.0 이후부터는 protocol의 선언에 @optional과 @required라는 modifier가 추가되었다. @optional은 꼭 구현하지 않아도 괜찮은 메소드들을 나타내고(앞 장에서 설명한 informal protocol처럼), @required는 기존의 protocol에 선언된 메소드들처럼 꼭 구현되어야 하는 메소드들을 나타낸다.
@protocol BaseballPlayer
- (void) slideHome;
- (void) catchBall;
- (void) throwBall;
@optional
- (void) drawHugeSalary;
@required
- (void) swingBat;
@end
Reference
[1] Dalrymple. M., Learn Objective-C on the Mac, Apress.
'Programming > Objective C' 카테고리의 다른 글
[Objective C] UIView, CGPoint, CGSize, CGRect (0) | 2010.12.30 |
---|---|
[Objective C] NSArray, NSMutableArray 객체 (0) | 2010.12.29 |
[Objective C] memory, retain, reference count, 메모리, 메모리관리 (0) | 2010.12.14 |