任何人都可以解释Objective-C中协议和类别之间的差异吗?你什么时候用另一个?
协议与Java中的接口是一样的:它本质上是一个契约,它说"实现这个协议的任何类都将实现这些方法."
另一方面,类别只是将方法绑定到类.例如,在Cocoa中,我可以创建一个类别,NSObject
这将允许我向NSObject
类(当然,所有子类)添加方法,即使我实际上没有访问权限NSObject
.
总结:协议指定了类将实现的方法; 类别将方法添加到现有类.
然后,应该清楚地正确使用每个:使用协议声明类必须实现的一组方法,并使用类别将方法添加到现有类.
协议说,"这里有一些我希望你实现的方法." 一个类别说,"我正在使用这些额外的方法扩展这个类的功能."
现在,我怀疑你的困惑源于苹果公司使用"非正式协议"这个短语.这是关键(也是最令人困惑的):非正式协议实际上根本不是协议.它实际上是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应用程序) .
分类:
类别是一种向现有类的所有实例添加新方法而不修改类本身的方法.
如果要在不派生该类或重写原始类的情况下向现有类添加功能,则可以使用类别.
假设您正在使用NSView
可可中的对象,并且您发现自己希望所有实例NSView
都能够执行某些操作.显然,你不能重写这个NSView
类,即使你从它派生,也不NSView
是你程序中的所有对象都是你的派生类型.解决方案是创建一个类别NSView
,然后在程序中使用该类别.只要您#import
包含类别声明的头文件,它就会显示为每个 NSView
对象都响应您在类别源文件中定义的方法.
协议:
协议是任何类可以选择实现的方法的集合.
如果要保证某个类将响应特定的一组方法,则可以使用协议.当一个类采用协议时,它承诺实现协议头中声明的所有方法.这意味着使用该类的任何其他类都可以确定将实现这些方法,而无需知道有关该类的任何其他内容.
这在创建一系列类似的类时非常有用,这些类都需要与公共"控制器"类进行通信.控制器类和受控类之间的通信都可以打包成单个协议.
旁注:objective-c语言不支持多重继承(一个类只能从一个超类派生),但协议可以提供许多相同的功能,因为一个类可以符合几种不同的协议.
据我所知,Protocols有点像Java的接口.协议声明了方法,但实现取决于每个类.类别似乎就像Ruby的mixins.使用Categories,您可以向现有类添加方法.甚至是内置类.