2011-09-19 93 views

回答

31

类别是在运行时添加到类中的方法的集合。由于Objective-C使用动态绑定,这意味着类中定义的方法对类及其所有子类都可用。具体而言,选择器在被调用的地方绑定到方法,而不是在编译期间或程序第一次加载时。当类(类别)加载时,类将被添加到类中。

协议定义符合它们的类承诺实现的方法签名的集合。一旦一个类声明它符合一个协议,就好像这个类的接口中声明的方法一样,并且继承规则完全相同:子类继承协议方法的声明和实现,但也可以选择覆盖超类实现。

协议本身可以扩展到产生新的协议。由原始协议中方法的超集组成。事实上,正如大多数类继承NSObject类一样,大多数协议都会扩展NSObject协议(协议名称和类名称位于不同的名称空间中)。这样可以发送声明为id<WhateverProtocol>的对象可以发送像-retain,-release等基本消息,而不会产生编译器警告。

+1

提及'obj-C'运行时间为+1 –

+1

最受欢迎的示例应该是: @protocol UITableViewDelegate 。 –

6

类别就像一个类的扩展。您可以将自己的方法添加到其他类(如NSString或其他任何类)。这意味着任何子类都可以获得这些方法。

协议是一个方法列表,它要求类确认它实现所有的方法(除非它使用@optional标签)。所以继承它的子类是毫无意义的。

编辑:

用于协议实现,我意识到,我并不清楚。 Protocol在其超类中实现的方法可以被继承,但是,我的意思是通常你不需要重写你的超类的协议方法。

+3

更具体地说:一子类继承了其父代的协议一致性。所以如果一个类符合,那么它的子类也符合。 –

+0

是的,这就是我所说的。谢谢。 – TheAmateurProgrammer

4

你的问题不清楚。您可能会问,子类是否继承其超类的协议和类别。 @theAmateurProgrammer已经回答了这个问题。

您可能还在问是否类别和协议本身可以继承其他类别和协议。对于类别,答案是否定的。对于协议,答案是肯定的,而事实上的协议应该总是继承只是喜欢这样的类:

@protocol SomeProtocol <NSObject> 
... 
@end 

这就是说任何一个符合<SomeProtocol>也符合<NSObject>(这是一个协议,以及一个类)。这允许您调用respondsToSelector:等方法,这对大多数协议实现都非常重要。

+0

这个答案的一半是对原始问题的评论。另一方面,它今天回答了我的问题,所以+1。谢谢。 –

2

协议就像Java中的接口。所以,一个类提供了一个访问它的协议。

就像在Java中一样,你可以“子类”化你的接口。

另一方面,类别是向类中添加更多方法的一种方法。限制是你不能添加任何具有类别的实例变量。您只能访问现有的实例变量。

这是非常有用的,但它避免了创建一个大的脆弱的子类层次结构。

所以,底线是,如果你想要一个视图不同的类符合标准接口,然后使用一个协议。如果你想添加一些方法到现有的类而没有子类的麻烦,去一个类别。

然而,有一点需要记住的是,当您将方法添加到某个类别时 - 我已经被同事提醒 - 这就是您在任何地方都可以使用这些方法。我已经在几个地方读到,一个常见的新手错误是对类别疯狂,始终使用它们,而不是创建可以完成这项工作的新类。因此,如果您正在考虑的新类别方法真的是特定的或者与业务功能紧密耦合的,那么它可能不应该是一个类别。他们真的只能用于基类的通用添加。

1

NSObject的符合NSObject的协议

@interface NSObject <NSObject> { 
    Class isa OBJC_ISA_AVAILABILITY; 
} 

假设我们有NSObject的子类

@interface FTGAnimal : NSObject 

@end 

@implementation FTGAnimal 

@end 

我们可以看到,FTGAnimal实际上符合NSObject的协议

if ([FTGAnimal conformsToProtocol:@protocol(NSObject)]) { 
     NSLog(@"FTGAnimal conforms to NSObject protocol"); 
}