在object-c中,協議的聲明類似於類介面的聲明,但是,協議沒有父類,而且不能定義成員變數,只能定義成員函數,而且成員函數並不是在這個協議中實現,而是要在使用它的類中實現。
1. 使用說明:
(1)協議的聲明方式,在.h中:
@protocol Myprotocol
-(void) myProtocolMethod;
@end
(2)協議的運用:
如果要使用一個協議,就要在聲明類的時候, 用<...>將協議名稱列出,並且需要在這個類的實現中也必須同時實現協議中聲明的成員函數。
例如,在你聲明自己的類 MyClass的時候, 可以這樣做:
@interface MyClass: NSObject <Myprotocol>
而在實現的 MyClass.m中,就需要實現協議Myprotocol中聲明的方法myProtocolMethod。
2. 例子代碼:
//1. Printing.h
@protocol Printing
-(void) print;
@end
//2. Fraction.h
#import <Foundation/NSObject.h>
#import "Printing.h"
@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
//3. 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;
}
-(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;
}
-(Fraction*) copyWithZone: (NSZone*) zone {
return [[Fraction allocWithZone: zone] initWithNumerator: numerator
denominator: denominator];
}
@end
//4. 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
//5. 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 );
}
@end
//6. 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" );
}
// false
if ( [comp conformsToProtocol: @protocol( NSCopying )] == YES ) {
printf( "Complex conforms to NSCopying\n" );
}
// free memory
[frac release];
[comp release];
return 0;
}
3. 編譯運行:
gcc -fconstant-string-class=NSConstantString -c main.m -I /GNUstep/System/Library/Headers
gcc -c Complex.m -I /GNUstep/System/Library/Headers
gcc -c Fraction.m -I /GNUstep/System/Library/Headers
gcc main.o Complex.o Printing.o -o main -L /GNUstep/System/Library/Libraries/ -lobjc -lgnustep-base
$ ./main.exe
The fraction is: 3/10
The complex number is: _f + _fi
Fraction conforms to NSCopying
4. 說明:
(1). protocol沒有父類,或者說是無類的;
(2). 如果一個類遵守了某個協議,那麼這個類的子類也遵守該協議;
(3). protocol只需要在.h中聲明就可以,所以,協議也不需要編譯成.o,也不可能編譯成.o,因為沒有.m檔案。
(4) . 正如例子中呈現的一樣,你的類中可以使用多個protocol, 例如:
@interface SomeClass <Protocol1, Protocol2, Protocol3>
...
@end