[Objective C] 10 Protocols

프로그래밍/iPhone Dev 2009. 11. 11. 17:47 Posted by galad
Protocols
자바의 인터페이스, C++의 버츄얼 클래스 같은 것
상속 받은 클래스에게 이것은 꼭 구현해야 한다고 규정 짓는 것. 말 그대로 프로토콜.

Printing.h
// 프로토콜 정의
@protocol Printing
-(void) print;
@end


Fraction.h
#import <Foundation/NSObject.h>
#import "Printing.h"

// <> 안이 프로토콜.
// NSObejct를 상속하고, Printing과 NSCopying을 프로토콜로 구현
@interface Fraction: NSObject <Printing, NSCopying> {
    int numerator;
    int denominator;
}

-(Fraction*) initWithNumerator: (int) n denominator: (int) d;
-(void) setNumerator: (int) d;
-(void) setDenominator: (int) d;
-(void) setNumerator: (int) n andDenominator: (int) d;
-(int) numerator;
-(int) denominator;
@end


Fraction.m
#import "Fraction.h"
#import <stdio.h>

@implementation Fraction
-(Fraction*) initWithNumerator: (int) n denominator: (int) d {
    self = [super init];

    if ( self ) {
        [self setNumerator: n andDenominator: d];
    }

    return self;
}

// Fraction.h에는 정의 되어 있지 않으나, 프로토콜 Printing에 정의되어 있는 것을 구현
-(void) print {
    printf( "%i/%i", numerator, denominator );
}

-(void) setNumerator: (int) n {
    numerator = n;
}

-(void) setDenominator: (int) d {
    denominator = d;
}

-(void) setNumerator: (int) n andDenominator: (int) d {
    numerator = n;
    denominator = d;
}

-(int) denominator {
    return denominator;
}

-(int) numerator {
    return numerator;
}

// print method와 마찬가지로 NSCopying 프로토콜을 구현
-(Fraction*) copyWithZone: (NSZone*) zone {
    return [[Fraction allocWithZone: zone] initWithNumerator: numerator
                                           denominator: denominator];
}
@end


Complex.h
#import <Foundation/NSObject.h>
#import "Printing.h"

@interface Complex: NSObject <Printing> {
    double real;
    double imaginary;
}

-(Complex*) initWithReal: (double) r andImaginary: (double) i;
-(void) setReal: (double) r;
-(void) setImaginary: (double) i;
-(void) setReal: (double) r andImaginary: (double) i;
-(double) real;
-(double) imaginary;
@end


Complex.m
#import "Complex.h"
#import <stdio.h>

@implementation Complex
-(Complex*) initWithReal: (double) r andImaginary: (double) i {
    self = [super init];

    if ( self ) {
        [self setReal: r andImaginary: i];
    }

    return self;
}

-(void) setReal: (double) r {
    real = r;
}

-(void) setImaginary: (double) i {
    imaginary = i;
}

-(void) setReal: (double) r andImaginary: (double) i {
    real = r;
    imaginary = i;
}

-(double) real {
    return real;
}

-(double) imaginary {
    return imaginary;
}

-(void) print {
//    printf( "%_f + %_fi", real, imaginary );
    printf( "%f + %f", real, imaginary );
}
@end


main.m
#import <stdio.h>
#import "Fraction.h"
#import "Complex.h"

int main( int argc, const char *argv[] ) {
    // create a new instance
    Fraction *frac = [[Fraction alloc] initWithNumerator: 3 denominator: 10];
    Complex *comp = [[Complex alloc] initWithReal: 5 andImaginary: 15];
    id <Printing> printable;
    id <NSCopying, Printing> copyPrintable;

    // print it
    printable = frac;
    printf( "The fraction is: " );
    [printable print];
    printf( "\n" );

    // print complex
    printable = comp;
    printf( "The complex number is: " );
    [printable print];
    printf( "\n" );

    // this compiles because Fraction comforms to both Printing and NSCopyable
    copyPrintable = frac;

    // this doesn't compile because Complex only conforms to Printing
    //copyPrintable = comp;

    // test conformance

    // true
    if ( [frac conformsToProtocol: @protocol( NSCopying )] == YES ) {
        printf( "Fraction conforms to NSCopying\n" );
    }
    else {
        printf( "Fraction doesn't conform to NSCopying\n" );
    }

    // false
    if ( [comp conformsToProtocol: @protocol( NSCopying )] == YES ) {
        printf( "Complex conforms to NSCopying\n" );
    }
    else {
        printf( "Complex doesn't conform to NSCopying\n" );
    }
   
    // test id type
    id f; // 그냥 id 타입으로 받아도 상관없음. 다만 엄격한 사용을 위해 위와 같이 protocol을 지정.
   
    f = frac;
    [f print];
    printf( "\n" );
   
    f = comp;
    [f print];
    printf( "\n" );

    // free memory
    [frac release];
    [comp release];

    system("PAUSE");
    return 0;
}


결과
The fraction is: 3/10
The complex number is: 5.000000 + 15.000000
Fraction conforms to NSCopying
Complex doesn't conform to NSCopying
3/10
5.000000 + 15.000000
계속하려면 아무 키나 누르십시오 . . .

- The methods that the protocol requires to be implemented are not required to be in the list of methods for the header file. As you can see, Complex.h doesn't have a definition for -(void) print, but it still implements it since it conforms to the protocol.
- One unique aspect of Objective-C's interface system is how you specify types. Rather than specifying it like Java or C++ as: Printing *someVar = ( Printing * ) frac; for example, you use the id type with a restricted protocol: id <Printing> var = frac; This allows you to dynamically specify a type that requires multiple protocols, all with one variable. Such as: id <Printing, NSCopying> var = frac;
- Much like using @selector for testing an object's inheritance, you can use @protocol to test for conformance of interfaces. [object conformsToProtocol: @protocol( SomeProtocol )] returns a BOOL if the object conforms to that protocol. This works the same for classes as well: [SomeClass conformsToProtocol: @protocol( SomeProtocol )].

'프로그래밍 > iPhone Dev' 카테고리의 다른 글

[Objective C] 12 Dealloc  (1) 2009.11.12
[Objective C] 11 Retain and Release  (0) 2009.11.12
[Objective C] 09 Posing  (0) 2009.11.10
[Objective C] 08 Categories  (0) 2009.11.09
[Objective C] 07 DynamicTypes  (0) 2009.10.30