分享

Protocol in Objective

 Kitsdk 2014-04-02

Protocol in Objective-C

image

前面提到了OOP的继承,但不像C++可以有多重继承,Objective-C是单一继承的,如果想要做到一个类别同时拥有多种型别的能力,可以透过实作其它型别的interface来达成这个目的。在Java/AS3是用”interface”这个关键字,在Objective-C则是用”@protocol”。(有写过Java/AS3的要特别注意不要把interface跟protocol搞混了,在Objective-C的interface等于Java/AS3的class,而protocol则是相当于interface)

直接来看看要怎么做吧。如果你要新增一个自定的protocol的话,可以直接在你的专案里新增一个protocol档:

image

当然,你要全部写在一起也没人反对,只是为了模组化以及以后的可重复使用考量,建议独立出来另外写。新增完成之后(它是一个header档),就可以开始来写了,程式码如下:

1
2
3
4
5
6
@protocol Drawable

-(void) draw;
-(void) changeColor;

@end

在Objective-C里的protocol是用@protocol这个语法来定义的。在上面这段程式码里,我放了两个方法,但没有写内容。接下来如果我要实作自这个protocol的话,所有定义在@protocol里的方法都得实作出来。另外,在Objective-C 2.0之后加了@required@optional的语法,可以让你设定这个method是不是必需一定要实作的项目。用法如下:

1
2
3
4
5
6
7
8
9
10
@protocol Drawable

@required
-(void) draw;
-(void) changeColor;

@optional
-(void) whateverMethod;

@end

如果没特别标明的,预设是@required。如果你要实作这个protocol的话,照英文字面来看,@required的部份是规定要实作的,@optional的话就随你高兴了。要注意的是@required跟@optional这两个语法的影响范围,是从它以下所有的method都会被影响,直到另一个directive或是@end为止,所以如果你要省略@required的话,记得那些method要写在@optional前面。接下来来看看要怎么实作这个protocol:

1
2
3
4
5
6
7
8
9
10
#import <Cocoa/Cocoa.h>
#import "Drawable.h"

@interface Book : NSObject <Drawable>
{
  int price;
}
@property int price;

@end

实作protocol的方法就是用”<>”标记,里面放protocol的名称。并不限定只能实作一个protocol,如果要实作多个protocol的话,则是用逗点分开:

1
@interface Book : NSObject <Drawable, Openable>

因为到目前为止,我们都还没实作那个protocol里定义的方法,所以这时候如果直接按下Build的话,就会跳出警告讯息:

image

接着来把该做的填一填吧。因为在protocol的地方已经有定义好了方法,所以在@interface的地方就不用再特别写一次,只要在@implementation里补上该实作的方法就行了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// --------------
// interface
// --------------
#import <Cocoa/Cocoa.h>
#import "Drawable.h"

@interface Book : NSObject <Drawable>
{
  int price;
}
@property int price;

@end

// --------------
// implementation
// --------------
#import "Book.h"
@implementation Book

@synthesize price;

// 实作方法draw
-(void) draw
{
  NSLog(@"draw me!");
}

// 实作方法changeColor
-(void) changeColor
{
  NSLog(@"change color!");
}

@end

如果你实作了所有@required的方法的话,则称为遵守(conform)或采纳(adopt)这个protocol(硬翻成中文还是觉得怪怪的,还是英文比较简洁直接)。若要检查某物件是否有乖乖遵守某个protocol的规定:

1
2
3
4
5
Book *book = [[Book alloc] init];
if ([book conformsToProtocol:@protocol(Drawable)] == YES)
{
  NSLog(@"the book is conform to Drawable protocol");
}

protocol本身也可以像一般类别的继承,例如:

1
2
3
4
5
6
7
@protocol A
-(void) methodA;
@end

@protocol B <A>
-(void) methodB;
@end

这时如果你要实作protocol B,则methodA跟methodB都需要实作。

另外,你也可以把protocol拿来当一般的型别定义来用,例如:

1
id <Drawable> some_object;

表示说这个some_object是个有实作Drawable这个protocol的物件,在编译阶段就可以先做型别检查。当然也可以一次多个,一样用逗点分开:

1
id <Drawable, Openable> some_object;

上面提到的这种用@protocol来定义方法的,称做formal protocol,从名字看大概猜得出来一定也有叫做informal protocol的东西,不过这个会在category的部份再做说明。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多