协议与类别
谁能解释一下 Objective-C 中协议和类别之间的区别? 你什么时候使用其中一种而不是另一种?
Can anyone explain the differences between Protocols and Categories in Objective-C? When do you use one over the other?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
协议与 Java 中的接口是一样的:它本质上是一个契约,它表示:“任何实现此协议的类也将实现这些方法。”
另一方面,类别只是绑定类的方法。 例如,在Cocoa中,我可以为
NSObject
创建一个类别,它允许我向NSObject
类添加方法(当然, ,所有子类),即使我实际上无权访问NSObject
。总结:协议指定类将实现哪些方法; 类别向现有类添加方法。
那么,每种方法的正确使用应该很清楚:使用协议声明类必须实现的一组方法,并使用类别向现有类添加方法。
A protocol is the same thing as an interface in Java: it's essentially a contract that says, "Any class that implements this protocol will also implement these methods."
A category, on the other hand, just binds methods to a class. For example, in Cocoa, I can create a category for
NSObject
that will allow me to add methods to theNSObject
class (and, of course, all subclasses), even though I don't really have access toNSObject
.To summarize: a protocol specifies what methods a class will implement; a category adds methods to an existing class.
The proper use of each, then, should be clear: Use protocols to declare a set of methods that a class must implement, and use categories to add methods to an existing class.
协议规定:“这里有一些我希望你实现的方法。” 一个类别说:“我正在使用这些附加方法扩展此类的功能。”
现在,我怀疑您的困惑源于苹果公司对“非正式协议”一词的使用。 这是关键(也是最令人困惑的)点:非正式协议实际上根本不是协议。 它实际上是 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 Cocoa 应用程序需要在早期版本的 Mac OS X 上运行)。A protocol says, "here are some methods I'd like you to implement." A category says, "I'm extending the functionality of this class with these additional methods."
Now, I suspect your confusion stems from Apple's use of the phrase "informal protocol". Here's the key (and most confusing) point: an informal protocol is actually not a protocol at all. It's actually a category on NSObject. Cocoa uses informal protocols pervasively to provide interfaces for delegates. Since the
@protocol
syntax didn't allow optional methods until Objective-C 2.0, Apple implemented optional methods to do nothing (or return a dummy value) and required methods to throw an exception. There was no way to enforce this through the compiler.Now, with Objective-C 2.0, the
@protocol
syntax supports the@optional
keyword, marking some methods in a protocol as optional. Thus, your class conforms to a protocol so long as it implements all the methods marked as@required
. The compiler can determine whether your class implements all the required methods, too, which is a huge time saver. The iPhone SDK exclusively uses the Objective-C 2.0@protocol
syntax, and I can't think of a good reason not to use it in any new development (except for Mac OS X Cocoa apps that need to run on earlier versions of Mac OS X).类别:
类别是一种向现有类的所有实例添加新方法而无需修改类本身的方法。
当您想要向现有类添加功能而不从该类派生或重写原始类时,可以使用类别。
假设您在 cocoa 中使用 NSView 对象,并且您发现自己希望 NSView 的所有实例都能够执行某些操作。 显然,您不能重写 NSView 类,即使您从它派生,程序中并非所有
NSView
对象都是您的派生类型。 解决方案是在NSView
上创建一个类别,然后在程序中使用它。 只要您#import
包含类别声明的头文件,它就会看起来好像每个NSView
对象都会响应您定义的方法类别源文件。协议:
协议是任何类都可以选择实现的方法的集合。
当您想要保证某个类将响应一组特定的方法时,您可以使用协议。 当一个类采用协议时,它承诺实现协议头中声明的所有方法。 这意味着使用该类的任何其他类都可以确定这些方法将被实现,而无需了解有关该类的任何其他信息。
当创建一系列相似的类并且都需要与公共“控制器”类进行通信时,这非常有用。 控制器类和受控类之间的通信可以全部打包到单个协议中。
旁注:objective-c 语言不支持多重继承(一个类只能从一个超类派生),但协议可以提供许多相同的功能,因为一个类可以符合多个不同的协议。
Categories:
A category is a way of adding new methods to all instances of an existing class without modifying the class itself.
You use a category when you want to add functionality to an existing class without deriving from that class or re-writing the original class.
Let's say you are using
NSView
objects in cocoa, and you find yourself wishing that all instances ofNSView
were able to perform some action. Obviously, you can't rewrite theNSView
class, and even if you derive from it, not all of theNSView
objects in your program will be of your derived type. The solution is to create a category onNSView
, which you then use in your program. As long as you#import
the header file containing your category declaration, it will appear as though everyNSView
object responds to the methods you defined in the catagory source file.Protocols:
A protocol is a collection of methods that any class can choose to implement.
You use a protocol when you want to provide a guarantee that a certain class will respond to a specific set of methods. When a class adopts a protocol, it promises to implement all of the methods declared in the protocol header. This means that any other classes which use that class can be certain that those methods will be implemented, without needing to know anyting else about the class.
This can be useful when creating a family of similar classes that all need to communicate with a common "controller" class. The communication between the controller class and the controlled classes can all be packaged into a single protocol.
Side note: the objective-c language does not support multiple inheritance (a class can only derive from one superclass), but much of the same functionality can be provided by protocols because a class can conform to several different protocols.
据我了解,协议有点像 Java 的接口。 协议声明方法,但实现取决于每个类。 类别似乎有点像 Ruby 的 mixin。 使用类别,您可以向现有类添加方法。 甚至内置类。
To my understanding Protocols are a bit like Java's Interfaces. Protocols declare methods , but the implementation is up to each class. Categories seems to be something like Ruby's mixins. With Categories you can add methods to existing classes. Even built-in classes.
协议允许您声明不限于任何特定类或类别的方法列表。 协议中声明的方法可以采用任何类/类别。 采用协议的类或类别必须实现协议中声明的所有必需方法。
类别允许您向现有类添加附加方法,但不允许附加实例变量。 类别添加的方法成为类类型的一部分。
A protocol allows you to declare a list of methods which are not confined to any particular class or categories. The methods declared in the protocol can be adopted any class/categories. A class or category which adopts a protocol must implements all the required methods declared in the protocol.
A category allows you to add additional methods to an existing class but they do not allow additional instance variables. The methods the category adds become part of the class type.
协议是实现指定方法的契约。 任何符合协议的对象都同意提供这些方法的实现。 协议的一个很好的用途是为委托定义一组回调方法(其中委托必须响应所有方法)。
类别提供了通过向当前对象添加方法(类或实例方法)来扩展当前对象的能力。 类别的一个很好的用途是扩展 NSString 类以添加以前没有的功能,例如添加一个方法来创建将接收器转换为 1337 5P34K 的新字符串。
Protocols are contracts to implement the specified methods. Any object that conforms to a protocol agrees to provide implementations for those methods. A good use of a protocol would be to define a set of callback methods for a delegate (where the delegate must respond to all methods).
Categories provide the ability to extend a current object by adding methods to it (class or instance methods). A good use for a category would be extending the NSString class to add functionality that wasn't there before, such as adding a method to create a new string that converts the receiver into 1337 5P34K.
SGKochan 的“Objective-C 编程”中的定义:
类别:
类别为您提供了一种简单的方法,可以将类的定义模块化为相关方法的组或类别。 它还为您提供了一种简单的方法来扩展现有的类定义,甚至无需访问该类的原始源代码,也无需创建子类。
协议:
协议是在类之间共享的方法列表。 协议中列出的方法没有对应的实现; 它们应该由其他人(比如你!)来实现。 协议提供了一种定义一组与指定名称以某种方式相关的方法的方法。 这些方法通常会被记录下来,以便您知道它们如何执行,并且如果需要,您可以在自己的类定义中实现它们。
协议列出了一组方法,其中一些方法您可以选择实现,另一些则需要您实现。 如果您决定实现特定协议的所有必需方法,则表示您遵守或采用该协议。 您可以定义一种协议,其中所有方法都是可选的,或者所有方法都是必需的。
Definitions from S.G.Kochan's "Programming in Objective-C":
Categories:
A category provides an easy way for you to modularize the definition of a class into groups or categories of related methods. It also gives you an easy way to extend an existing class definition without even having access to the original source code for the class and without having to create a subclass.
Protocols:
A protocol is a list of methods that is shared among classes. The methods listed in the protocol do not have corresponding implementations; they’re meant to be implemented by someone else (like you!). A protocol provides a way to define a set of methods that are somehow related with a specified name. The methods are typically documented so that you know how they are to perform and so that you can implement them in your own class definitions, if desired.
A protocol list a set of methods, some of which you can optionally implement, and others that you are required to implement. If you decide to implement all of the required methods for a particular protocol, you are said to conform to or adopt that protocol. You are allowed to define a protocol where all methods are optional, or one where all are required.