协议定义了一系列方法,遵从此协议的对象应该实现它们(如果这些方法不是可选的, 那么就必须实现)。于是,我们可以用协议把自己所写的API
之中的实现细节隐藏起来,将返回的对象设计为遵从此协议的纯id
类型。
这样的话,想要隐藏的类名就不会出现在API
之中了。若是接口背后有多个不同的实现类,而你又不想指明具体使用哪个类,那么可以考虑用这个办法——因为有时候这些类可能会变,有时候它们又无法容纳于标准的类继承体系中,因而不能以某个公共基类来统一表示。
此概念经常称为“匿名对象"(anonymous object)
,这与其他语言中的“匿名对象”不同,在那些语言中,该词是指以内联形式所创建出来的无名类,而此词在Objective-C
中则不是这个意思。
我们之前说的委托与数据源对象,就用到了这个方法。例如在定义“受委托者(delegate)”属性时:
@property {nonatomic, weak) id <EOCDelegate> delegate;
由于该属性的类型是id<EOCDelegate>
,所以实际上任何类的对象都能充当这一属性, 即便该类不继承自NSObject
也可以,只要遵循EOCDelegate
协议就行。对于具备此属性的类来说,delegate
就是“匿名的”(ammymous)。如有需要,可在运行期査出此对象所属的类型(参见第14条)。然而这样做不太好,因为指定属性类型时所写的那个EOCDelegate
契约已经表明此对象的具体类型无关紧要了。
当然还有其它的用法,这里我们就不举例了。
要点
- 协议可在某种程度上提供匿名类型。具体的对象类型可以淡化成遵从某协议的
id
类型,协议里规定了对象所应实现的方法。 - 使用匿名对象来隐藏类型名称(或类名)。
- 如果具体类型不重要,重要的是对象能够响应(定义在协议里的)特定方法,那么可使用匿名对象来表示。