Objective-C协议和类别可以继承吗?

时间:2022-09-06 20:10:35

I am little confused about some concepts around Objective-C protocols and categories.

我对Objective-C协议和类别的一些概念有点困惑。

Can protocols and categories be inherited by subclasses in Objective-C?

协议和类别可以被Objective-C中的子类继承吗?

5 个解决方案

#1


31  

Categories are collections of methods that are added to a class at run time. Because Objective-C uses dynamic binding, this means that the methods defined in a category are available to the class and all of its subclasses. Specifically selectors are bound to methods at the point where they are invoked, not during compilation or when the program first loads. Categories are added to classes when they (the categories) are loaded.

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

Protocols define collections of method signatures that the classes conforming to them promise to implement. Once a class has declared that it conforms to a protocol its as if the methods are declared in that class's interface and the rules of inheritance are exactly the same: subclasses inherit the declaration and implementation of the protocol methods but may also choose to override the superclass implementation.

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

Protocols themselves can be extended to produce new protocols. consisting of a superset of the methods in the original protocol. In fact, just as most classes inherit from the NSObject class, most protocols extend the NSObject protocol (protocol names and class names are in different name spaces). This is so that objects declared as id<WhateverProtocol> can be sent basic messages like -retain, -release and so on without generating compiler warnings.

协议本身可以被扩展以产生新的协议。由原始协议中方法的超集组成。事实上,正如大多数类继承自NSObject类一样,大多数协议扩展了NSObject协议(协议名称和类名称在不同的名称空间中)。这样就可以将声明为id 的对象发送诸如-retain、-release等基本消息,而无需生成编译器警告。

#2


6  

Categories are like an extension to a class. You can add your own methods to other classes (such as NSString or anything else). Which means that any subclass gets the methods as well.

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

Whereas a protocol are a list of methods that requires the class that confirms to it to implement all of it (unless it uses the @optional tag). So there is no point of it's subclass to inherit it.

而协议是一个方法列表,需要向其确认的类来实现所有的方法(除非它使用@optional标记)。所以它没有子类来继承它。

Edit:

编辑:

For the protocol implementation, I realized I wasn't clear enough. Protocol Methods that were implemented in it's superclass can be inherited, however, what I meant was usually you don't need to override your superclass's protocol method.

对于协议实现,我意识到我不够清楚。在它的超类中实现的协议方法可以被继承,但是,我的意思是通常您不需要重写超类的协议方法。

#3


4  

Your question is unclear. You may be asking whether subclasses inherit the protocols and categories of their superclass. @theAmateurProgrammer has answered this.

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

You may also be asking whether categories and protocols can themselves inherit from other categories and protocols. For categories, the answer is no. For protocols, the answer is yes, and in fact protocols should almost always inherit just like classes like this:

您可能还会问,类别和协议本身是否可以从其他类别和协议继承。对于类别来说,答案是否定的。对于协议来说,答案是肯定的,事实上协议应该总是继承像这样的类:

@protocol SomeProtocol <NSObject>
...
@end

This says that anything that conforms to <SomeProtocol> also conforms to <NSObject> (which is a protocol as well as a class). This allows you to call methods like respondsToSelector:, which is very important for most protocol implementations.

这说明任何符合 的内容也符合 (它是一个协议,也是一个类)。这允许您调用respondsToSelector:等方法,这对于大多数协议实现非常重要。

#4


2  

Protocols are like interfaces in Java. So, a class provides a protocol for accessing it.

协议就像Java中的接口。因此,类提供了访问它的协议。

You can "subclass" protocols just like in Java you can "subclass" interfaces.

您可以“子类化”协议,就像在Java中一样,您可以“子类化”接口。

Categories on the other hand are a way to add more methods to a class. The restriction is you can't add any instance variables with a category. You can only access the existing instance variables.

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

It's very useful though because it avoids creating a large fragile subclass hierarchy.

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

So, bottom line is, if you want a view different classes to conform to a standard interface, then use a protocol. If you want to add a few methods to an existing class without the hassle of subclassing, go for a category.

所以,底线是,如果你想让一个视图不同的类符合一个标准接口,那么就使用一个协议。如果您想在现有的类中添加一些方法,而不需要进行子类化,请选择一个类别。

However, one thing to bear in mind is that when you add methods to a category - something I've been reminded of by workmates - is that you're making those methods available everywhere. I've read in a few places that a common newbie mistake is to go crazy with categories, using them all the time instead of creating new classes that would do the job.

然而,需要记住的一件事是,当您向一个类别添加方法时——我被同事提醒过——您正在使这些方法在任何地方都可用。我在一些地方读到过,一个常见的新手错误就是疯狂地使用类别,一直使用它们,而不是创建新的类来完成这项工作。

So, if the new category method that you're considering is really specific or rather - tightly coupled - to a business function, then probably it shouldn't be a category. They really should only be used for generic additions to the base class.

因此,如果您正在考虑的新类别方法确实是特定的或与业务功能紧密耦合的,那么它可能不应该是一个类别。它们应该只用于基类的泛型添加。

#5


1  

NSObject conforms to NSObject protocol

NSObject符合NSObject协议

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

Say we have a subclass of NSObject

假设我们有一个NSObject的子类

@interface FTGAnimal : NSObject

@end

@implementation FTGAnimal

@end

We can see that FTGAnimal actually conforms to NSObject protocol

我们可以看到FTGAnimal实际上遵守NSObject协议

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

#1


31  

Categories are collections of methods that are added to a class at run time. Because Objective-C uses dynamic binding, this means that the methods defined in a category are available to the class and all of its subclasses. Specifically selectors are bound to methods at the point where they are invoked, not during compilation or when the program first loads. Categories are added to classes when they (the categories) are loaded.

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

Protocols define collections of method signatures that the classes conforming to them promise to implement. Once a class has declared that it conforms to a protocol its as if the methods are declared in that class's interface and the rules of inheritance are exactly the same: subclasses inherit the declaration and implementation of the protocol methods but may also choose to override the superclass implementation.

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

Protocols themselves can be extended to produce new protocols. consisting of a superset of the methods in the original protocol. In fact, just as most classes inherit from the NSObject class, most protocols extend the NSObject protocol (protocol names and class names are in different name spaces). This is so that objects declared as id<WhateverProtocol> can be sent basic messages like -retain, -release and so on without generating compiler warnings.

协议本身可以被扩展以产生新的协议。由原始协议中方法的超集组成。事实上,正如大多数类继承自NSObject类一样,大多数协议扩展了NSObject协议(协议名称和类名称在不同的名称空间中)。这样就可以将声明为id 的对象发送诸如-retain、-release等基本消息,而无需生成编译器警告。

#2


6  

Categories are like an extension to a class. You can add your own methods to other classes (such as NSString or anything else). Which means that any subclass gets the methods as well.

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

Whereas a protocol are a list of methods that requires the class that confirms to it to implement all of it (unless it uses the @optional tag). So there is no point of it's subclass to inherit it.

而协议是一个方法列表,需要向其确认的类来实现所有的方法(除非它使用@optional标记)。所以它没有子类来继承它。

Edit:

编辑:

For the protocol implementation, I realized I wasn't clear enough. Protocol Methods that were implemented in it's superclass can be inherited, however, what I meant was usually you don't need to override your superclass's protocol method.

对于协议实现,我意识到我不够清楚。在它的超类中实现的协议方法可以被继承,但是,我的意思是通常您不需要重写超类的协议方法。

#3


4  

Your question is unclear. You may be asking whether subclasses inherit the protocols and categories of their superclass. @theAmateurProgrammer has answered this.

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

You may also be asking whether categories and protocols can themselves inherit from other categories and protocols. For categories, the answer is no. For protocols, the answer is yes, and in fact protocols should almost always inherit just like classes like this:

您可能还会问,类别和协议本身是否可以从其他类别和协议继承。对于类别来说,答案是否定的。对于协议来说,答案是肯定的,事实上协议应该总是继承像这样的类:

@protocol SomeProtocol <NSObject>
...
@end

This says that anything that conforms to <SomeProtocol> also conforms to <NSObject> (which is a protocol as well as a class). This allows you to call methods like respondsToSelector:, which is very important for most protocol implementations.

这说明任何符合 的内容也符合 (它是一个协议,也是一个类)。这允许您调用respondsToSelector:等方法,这对于大多数协议实现非常重要。

#4


2  

Protocols are like interfaces in Java. So, a class provides a protocol for accessing it.

协议就像Java中的接口。因此,类提供了访问它的协议。

You can "subclass" protocols just like in Java you can "subclass" interfaces.

您可以“子类化”协议,就像在Java中一样,您可以“子类化”接口。

Categories on the other hand are a way to add more methods to a class. The restriction is you can't add any instance variables with a category. You can only access the existing instance variables.

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

It's very useful though because it avoids creating a large fragile subclass hierarchy.

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

So, bottom line is, if you want a view different classes to conform to a standard interface, then use a protocol. If you want to add a few methods to an existing class without the hassle of subclassing, go for a category.

所以,底线是,如果你想让一个视图不同的类符合一个标准接口,那么就使用一个协议。如果您想在现有的类中添加一些方法,而不需要进行子类化,请选择一个类别。

However, one thing to bear in mind is that when you add methods to a category - something I've been reminded of by workmates - is that you're making those methods available everywhere. I've read in a few places that a common newbie mistake is to go crazy with categories, using them all the time instead of creating new classes that would do the job.

然而,需要记住的一件事是,当您向一个类别添加方法时——我被同事提醒过——您正在使这些方法在任何地方都可用。我在一些地方读到过,一个常见的新手错误就是疯狂地使用类别,一直使用它们,而不是创建新的类来完成这项工作。

So, if the new category method that you're considering is really specific or rather - tightly coupled - to a business function, then probably it shouldn't be a category. They really should only be used for generic additions to the base class.

因此,如果您正在考虑的新类别方法确实是特定的或与业务功能紧密耦合的,那么它可能不应该是一个类别。它们应该只用于基类的泛型添加。

#5


1  

NSObject conforms to NSObject protocol

NSObject符合NSObject协议

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

Say we have a subclass of NSObject

假设我们有一个NSObject的子类

@interface FTGAnimal : NSObject

@end

@implementation FTGAnimal

@end

We can see that FTGAnimal actually conforms to NSObject protocol

我们可以看到FTGAnimal实际上遵守NSObject协议

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