协议的必要性是抽象没有层次相关的类的方法。
类似的事情也可以在包含所有这些方法和子类的类(接口)的帮助下完成?(由于多重继承问题,这实际上是不可能的,因为一个类必须已经从 NSObject 派生。忽略 NSProxy 案例)
协议除了类还能做哪些特别的事情?
协议是否试图仅解决多重继承问题?
协议的必要性是抽象没有层次相关的类的方法。
类似的事情也可以在包含所有这些方法和子类的类(接口)的帮助下完成?(由于多重继承问题,这实际上是不可能的,因为一个类必须已经从 NSObject 派生。忽略 NSProxy 案例)
协议除了类还能做哪些特别的事情?
协议是否试图仅解决多重继承问题?
协议的主要优点是,它们描述了一个对象应该能够做什么,而不需要强制子类化。在没有多重继承的语言中,如果您希望其他程序员能够使用您的类,则需要这种机制。(见代表团)
例如,Java 有类似的东西,称为接口。
这意味着一个巨大的优势,因为构建动态系统非常容易,因为我可以允许其他开发人员通过明确定义的协议来增强我的类。
一个实际的例子:
我只是在设计一个 REST API,我正在提供一个 Objective-C 客户端库。
由于我的 api 需要有关用户的信息,因此我添加了一个协议
@protocol VSAPIClientUser <NSObject>
-(NSString *)lastName;
-(NSString *)firstName;
-(NSString *)uuid;
@end
任何我需要这个用户信息的地方,我都会有一个基本的 id-object,它必须符合这个协议
-(void)addUserWithAttributes:(id<VSAPIClientUser>)user;
你可以把这行读成:“我不在乎,你在这里提供什么样的对象,只要它知道lastName
,firstName
和uuid
”。所以我不知道那个物体的其余部分是什么样子的——我不在乎。
作为图书馆作者,我可以安全地使用它:
NSDictionary *userAttributes = @{@"last_name" : [user lastName],
@"first_name": [user firstName],
@"uuid": [user uuid]};
顺便说一句:我不会将缺少多继承称为问题。这只是另一种设计。
“[…] 如果我今天重新审视这个决定,我什至可能会取消单一继承。继承并不是那么重要。封装是 OOP 的持久贡献。” — 有人问 Brad Cox,为什么 Objective-C 没有多重继承。(编程大师:与主要编程语言的创造者的对话,第 259 页)
作为另一种观点......
面向对象编程最基本的价值来自于能够直接对现实世界的关系建模,而不是将它们转换为抽象的和模糊等价的计算机世界结构。当一种语言要求您以不同于您可以用来描述您的问题的术语来考虑解决方案的实现时,它作为 OOP 工具是有缺陷的。(请注意,我没有说“无用”。:))
现实世界的对象具有依赖于上下文的各种角色。这些角色可以有状态。因此,我同意缺乏多重继承是建模容易的障碍。Objective-C 协议、Java 接口以及您应该更喜欢组合而不是继承的主张都是对 OOP 优势的基本部分的否定。
C++ 抽象类的众多用途之一是定义接口(指定可重用的契约)。然而,也有其他编程语言,例如 Objective C,在这个意义上对接口有一个单独的概念。在 Objective C 中,它被称为协议。
这种结构的广泛使用确实需要一种将多个合同附加到一个对象的方法。如果允许这样的接口相互继承,那么这必须是多重继承才有用。
但是,这与类之间的多重继承不同。
协议并没有试图解决多重继承问题。他们试图将合约规范与对象(数据+代码)规范分开。它们实际上可以做的比一个类少得多(如果你忽略了多重继承方面),这就是它们作为一个单独的概念存在的原因。
与从类继承相比,实现协议通常要考虑的限制更少(更安全)。