有人能解释Objective-C中协议和类别之间的差异吗?你何时使用其中一个?
答案 0 :(得分:89)
协议与Java中的接口相同:它本质上是一个契约,“任何实现此协议的类也将实现这些方法。”
另一方面,类别只是将方法绑定到类。例如,在 Cocoa 中,我可以为NSObject
创建一个类别,允许我将方法添加到NSObject
类(当然还有所有子类),< em>即使我真的无法访问NSObject
。
总结一下:协议指定了一个类将实现的方法;类别将方法添加到现有类。
然后,应该清楚地正确使用每个:使用协议来声明类必须实现的一组方法,并使用类别将方法添加到现有类。
答案 1 :(得分: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 Cocoa应用程序) Mac OS X)。
答案 2 :(得分:16)
分类:
类别是一种向现有类的所有实例添加新方法而不修改类本身的方法。
如果要在不派生该类或重写原始类的情况下向现有类添加功能,则使用类别。
假设您在cocoa中使用NSView
个对象,并且您发现自己希望NSView
的所有实例都能够执行某些操作。显然,您无法重写NSView
类,即使您从中派生,也不是程序中的所有NSView
对象都是派生类型。解决方案是在NSView
上创建一个类别,然后在程序中使用该类别。只要您#import
包含类别声明的头文件,它就会显示为每个 NSView
对象响应您在类别源文件中定义的方法。
协议:
协议是任何类可以选择实现的方法集合。
如果要保证某个类将响应特定的一组方法,则使用协议。当一个类采用协议时,它承诺实现协议头中声明的所有方法。这意味着使用该类的任何其他类都可以确定将实现这些方法,而无需了解该类的其他任何内容。
这在创建一个类似的类族时非常有用,这些类都需要与公共“控制器”类进行通信。控制器类和受控类之间的通信都可以打包成单个协议。
附注:objective-c语言不支持多重继承(一个类只能从一个超类派生),但协议可以提供很多相同的功能,因为一个类可以符合几种不同的协议。
答案 3 :(得分:5)
据我所知,Protocols有点像Java的接口。协议声明了方法,但实现取决于每个类。类别似乎就像Ruby的mixins。使用Categories,您可以向现有类添加方法。甚至是内置类。
答案 4 :(得分:3)
协议允许您声明不限于任何特定类或类别的方法列表。协议中声明的方法可以采用任何类/类别。采用协议的类或类必须实现协议中声明的所有必需方法。
类别允许您向现有类添加其他方法,但它们不允许其他实例变量。类别添加的方法成为类类型的一部分。
答案 5 :(得分:1)
协议是实现指定方法的合同。符合协议的任何对象都同意为这些方法提供实现。协议的一个好用途是为委托定义一组回调方法(委托必须响应所有方法)。
Categories提供了通过向其添加方法(类或实例方法)来扩展当前对象的能力。对类别的一个很好的用途是扩展NSString类以添加以前不存在的功能,例如添加一个方法来创建一个将接收器转换为1337 5P34K的新字符串。
NSString *test = @"Leet speak";
NSString *leet = [test stringByConvertingToLeet];
答案 6 :(得分:1)
S.G.Kochan的“Objective-C编程”中的定义:
<强>分类强>
类别为您提供了一种简单的方法,可以将类的定义模块化为相关方法的组或类别。它还为您提供了一种简单的方法来扩展现有的类定义,甚至无需访问类的原始源代码,也无需创建子类。
<强>协议强>
协议是类之间共享的方法列表。协议中列出的方法没有相应的实现方式;它们意味着由其他人实施(像你一样!)。协议提供了一种定义一组方法的方法,这些方法以某种方式与指定的名称相关。通常会记录这些方法,以便您了解它们的执行方式,以便您可以根据需要在自己的类定义中实现它们。 协议列表是一组方法,其中一些方法可以选择实现,另一些方法则需要实现。如果您决定为特定协议实现所有必需的方法,则说您遵守或采用该协议。您可以定义一个协议,其中所有方法都是可选的,或者是所有方法都需要的协议。