类别与非正式协议

时间:2010-02-02 10:52:45

标签: iphone objective-c protocols categories

我想我理解(正式)协议和类别之间的区别。现在,如果我做对了,非正式协议应该是类别(通常在NSObject上定义),这些类别用于某些目的(可能只提供实现其中列出的部分方法的机会,与正式协议不同)。我需要确定一下: 任何人都可以确认非正式协议只是一个类别(或解释差异)? 谢谢。

4 个答案:

答案 0 :(得分:8)

Category是类功能的扩展 - 这是一些方法的实现:

@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

答案 1 :(得分:5)

非正式协议确实只是在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

答案 2 :(得分:3)

The Objective-C Manual说你是对的 - 非正式协议通常是类别。

  

除了正式协议之外,您还可以通过将类别声明中的方法分组来定义非正式协议:

但是,您可以通过口口相传来实现非正式协议 - 当然,在实现接口构建器的委托方法时,我从未试图寻找类别;除了非正式协议之外,类别也用于other things

答案 3 :(得分:0)

协议只是接口的定义。

一个类别(针对NSObject)既是接口的定义,也是所有子类(NSObject)将继承的接口的实现,除非它们覆盖类别的方法。

虽然Apple过去选择通过针对NSObject创建类别来定义非正式协议并不意味着一个是另一个的定义。

通过声明接口但不实际实现它,可以半定义类别的事实应该(在公正和公平的世界中)导致编译错误,因为Objective-C编译器肯定会抱怨'不完整的实现'用于真实的接口。但是他们已被滥用了足够长的时间,以至于你可以预期这种行为不会改变。