【问题标题】:Categories vs Informal Protocols类别与非正式协议
【发布时间】:2010-02-02 10:52:44
【问题描述】:
我想我理解(正式)协议和类别之间的区别。现在,如果我做对了,非正式协议应该是用于特定目的的类别(通常在 NSObject 上定义)(与正式协议不同,可能只实现其中列出的部分方法)。我需要确定这一点:
任何人都可以确认非正式协议只是一个类别(或解释差异)吗?
谢谢。
【问题讨论】:
标签:
iphone
objective-c
protocols
categories
【解决方案1】:
类别是类功能的扩展——这是一些方法的实现:
@interface NSObject (MyCategory)
- (void)doSomething;
@end
...
@implementation NSObject (MyCategory)
- (void)doSomething {
// do something...
}
@end
正式的协议是完全不同的东西。如果您熟悉其他一些面向对象的语言,那么它就像接口(Java、C++、C# 等)。
协议可以像这样附加到任何类实现:
@protocol MyProtocol
@required
- (void)doSomething;
@optional
- (void)doSomethingOptional;
@end
...
@interface MyClass : NSObject <MyProtocol> {
}
@end
...
@implementation MyClass
- (void)doSomething {
// do something...
}
@end
根据文档,非正式协议是 NSObject 类的类别(我从未使用过这种方法):
@interface NSObject (MyInformalProtocol)
- (void)doSomething;
@end
...
@implementation NSObject (MyInformalProtocol)
- (void)doSomething {
// do something...
}
@end
【解决方案2】:
非正式协议确实只是在 NSObject 上定义的简单类别,但如果您要定义委托接口,则有更好的方法。相反,使用带有可选方法的正式协议(即真实的、实际的@protocol 定义)。这使您可以在编译时测试委托的类型(即它实际上是否符合协议),如果您使用了错误的对象,则会收到警告。
@protocol GLFunkyObjectDelegate
@optional
-(void)funkyObject: (GLFunkyObject *)obj willDoSomething: (GLSomeThing *)thing;
-(void)funkyObject: (GLFunkyObject *)obj didDoSomething: (GLSomeThing *)thing;
@end
@interface GLFunkyObject {
id <GLFunkyObjectDelegate> delegate;
}
//...
@end
【解决方案4】:
协议只是接口的定义。
一个类别(针对 NSObject)既是一个接口的定义,也是该接口的一个实现,所有子类(NSObject 的)都将继承,除非它们覆盖了该类别的方法。
虽然 Apple 过去选择通过针对 NSObject 创建类别来定义非正式协议,但这并不意味着一个就是另一个的定义。
您可以通过声明接口但不实际实现它来半定义一个类别,这应该(在公正和公平的世界中)导致编译错误发生,因为 Objective-C 编译器肯定会抱怨“不完整的实现” ' 用于真实接口。但是他们已经被滥用了足够长的时间,以至于你可以期望他们的行为不会改变。