39

谁能解释一下Objective-C 中协议类别之间的区别?你什么时候使用一个而不是另一个?

4

7 回答 7

91

协议与 Java 中的接口相同:它本质上是一个约定,“任何实现此协议的类也将实现这些方法”。

另一方面,类别只是将方法绑定到一个类。例如,在Cocoa中,我可以为其创建一个类别,NSObject这将允许我向NSObject该类(当然还有所有子类)添加方法,即使我真的无法访问NSObject.

总结一下:协议指定类将实现哪些方法;类别将方法添加到现有类。

那么,每种方法的正确使用应该很清楚:使用协议来声明类必须实现的一组方法,并使用类别向现有类添加方法。

于 2008-12-11T21:40:27.097 回答
29

一个协议说,“这里有一些我希望实现的方法。” 一个类别说:“我正在使用这些附加方法扩展这个类的功能。”

现在,我怀疑您的困惑源于 Apple 使用了“非正式协议”一词。这是关键(也是最令人困惑的)点:非正式协议实际上根本不是协议。它实际上是 NSObject 上的一个类别。Cocoa 普遍使用非正式协议来为委托提供接口。由于该@protocol语法在 Objective-C 2.0 之前不允许使用可选方法,因此 Apple 实现了不做任何事情(或返回虚拟值)的可选方法,并要求方法抛出异常。无法通过编译器强制执行此操作。

现在,在 Objective-C 2.0 中,@protocol语法支持@optional关键字,将协议中的一些方法标记为可选。因此,只要你的类实现了所有标记为 的方法,它就符合协议@required。编译器可以确定您的类是否也实现了所有必需的方法,这可以节省大量时间。iPhone SDK 专门使用 Objective-C 2.0@protocol语法,我想不出在任何新开发中不使用它的充分理由(除了需要在早期版本的 Mac OS X 上运行的 Mac OS X Cocoa 应用程序) .

于 2008-12-11T21:56:44.820 回答
16

分类:

类别是一种在不修改类本身的情况下向现有类的所有实例添加新方法的方法。

当您想将功能添加到现有类而不从该类派生或重写原始类时,您可以使用类别。

假设您NSView在 cocoa 中使用对象,并且您发现自己希望所有实例NSView都能够执行某些操作。显然,您不能重写NSView该类,即使您从它派生,也不是NSView程序中的所有对象都属于您的派生类型。解决方案是在 上创建一个类别NSView,然后在程序中使用它。只要您#import的头文件包含您的类别声明,它就会看起来好像每个 NSView对象都响应您在类别源文件中定义的方法。

协议:

协议是任何类都可以选择实现的方法的集合。

当您想要保证某个类将响应一组特定的方法时,您可以使用协议。当一个类采用协议时,它承诺实现协议头中声明的所有方法。这意味着使用该类的任何其他类都可以确定将实现这些方法,而无需了解有关该类的任何其他信息。

这在创建所有需要与公共“控制器”类通信的类似类家族时很有用。控制器类和受控类之间的通信都可以打包成一个协议。

旁注:objective-c 语言不支持多重继承(一个类只能从一个超类派生),但协议可以提供许多相同的功能,因为一个类可以符合几个不同的协议。

于 2008-12-11T21:41:31.777 回答
5

据我了解,协议有点像 Java 的接口。协议声明方法,但实现取决于每个类。类别似乎类似于 Ruby 的 mixins。使用类别,您可以将方法添加到现有类。甚至内置类。

于 2008-12-11T21:44:35.997 回答
4

协议允许您声明不限于任何特定类或类别的方法列表。协议中声明的方法可以被任何类/类别采用。采用协议的类或类别必须实现协议中声明的所有必需方法。

类别允许您向现有类添加额外的方法,但它们不允许额外的实例变量。类别添加的方法成为类类型的一部分。

于 2011-09-04T18:53:37.887 回答
1

协议是实现指定方法的合约。任何符合协议的对象都同意为这些方法提供实现。协议的一个很好的用途是为委托定义一组回调方法(委托必须响应所有方法)。

类别提供通过向其添加方法(类或实例方法)来扩展当前对象的能力。类别的一个很好的用途是扩展 NSString 类以添加以前没有的功能,例如添加一个方法来创建将接收器转换为 1337 5P34K 的新字符串。

NSString *test = @"Leet speak";
NSString *leet = [test stringByConvertingToLeet];
于 2009-03-19T10:11:56.047 回答
1

SGKochan 的“Objective-C 编程”中的定义:

分类:

类别为您提供了一种简单的方法,可以将类的定义模块化为相关方法的组或类别。它还为您提供了一种扩展现有类定义的简单方法,甚至无需访问该类的原始源代码,也无需创建子类。

协议:

协议是类之间共享的方法列表。协议中列出的方法没有对应的实现;它们是由其他人实施的(比如你!)。协议提供了一种方法来定义一组与指定名称相关的方法。这些方法通常会记录在案,以便您知道它们是如何执行的,并且如果需要,您可以在自己的类定义中实现它们。协议列出了一组方法,其中一些您可以选择实现,而另一些则需要您实现。如果您决定为特定协议实现所有必需的方法,则称您符合或采用该协议。您可以定义一个协议,其中所有方法都是可选的,或者所有方法都是必需的。

于 2012-06-14T11:00:00.947 回答