在Objective-C中使用类别重写方法

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

Can I use a class category to override a method that is already implemented using a category? Like this:

我可以使用类类别来覆盖已经使用类别实现的方法吗?是这样的:

1) Original method

1)原方法

-(BOOL) method {
  return true;
}

2) Overrided method

2)覆盖方法

-(BOOL) method {
  NSLog(@"error?"); 
  return true; 
}

Will this work, or is this illegal?

这行得通吗,还是非法的?

4 个解决方案

#1


136  

From Apple documentation:

从苹果公司文档:

Although the Objective-C language currently allows you to use a category to override methods the class inherits, or even methods declared in the class interface, you are strongly discouraged from doing so. A category is not a substitute for a subclass. There are several significant shortcomings to using a category to override methods:

尽管Objective-C语言目前允许您使用一个类别来覆盖类继承的方法,甚至是类接口中声明的方法,但是强烈建议您不要这样做。类别不是子类的替代品。使用类别覆盖方法有几个明显的缺点:

  • When a category overrides an inherited method, the method in the category can, as usual, invoke the inherited implementation via a message to super. However, if a category overrides a method that exists in the category's class, there is no way to invoke the original implementation.

    当类别重写继承的方法时,类别中的方法通常可以通过消息调用继承的实现到super。但是,如果一个类别覆盖了类中存在的方法,那么就没有办法调用原始实现。

  • A category cannot reliably override methods declared in another category of the same class.

    类别不能可靠地覆盖在同一类的另一个类别中声明的方法。

    This issue is of particular significance because many of the Cocoa classes are implemented using categories. A framework-defined method you try to override may itself have been implemented in a category, and so which implementation takes precedence is not defined.

    这个问题特别重要,因为许多Cocoa类都是使用类别来实现的。您试图覆盖的框架定义方法本身可能已经在一个类别中实现,因此没有定义哪个实现优先级。

  • The very presence of some category methods may cause behavior changes across all frameworks. For example, if you override the windowWillClose: delegate method in a category on NSObject, all window delegates in your program then respond using the category method; the behavior of all your instances of NSWindow may change. Categories you add on a framework class may cause mysterious changes in behavior and lead to crashes.

    某些类别方法的存在可能会导致所有框架的行为变化。例如,如果重写NSObject上类别中的windowWillClose: delegate方法,则程序中的所有窗口委托使用category方法进行响应;所有NSWindow实例的行为都可能改变。在框架类中添加的类别可能会导致行为的神秘变化并导致崩溃。

#2


18  

You can do this by adapting Class Cluster approach, or using methods swizzling technique.

您可以通过采用类集群方法或使用方法swizzle技术来实现这一点。

Otherwise, the behavior of two or more categorized methods is undefined

否则,两个或多个分类方法的行为就没有定义

#3


8  

Old documentation link is dead; best replacement I could find was here: Apple Docs:

旧的文档链接已经失效;我能找到的最佳替代品是:苹果文档:

Avoid Category Method Name *es

Because the methods declared in a category are added to an existing class, you need to be very careful about method names.

因为在类中声明的方法被添加到一个现有类中,所以您需要非常注意方法名称。

If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime. This is less likely to be an issue if you’re using categories with your own classes, but can cause problems when using categories to add methods to standard Cocoa or Cocoa Touch classes.

如果在类别中声明的方法的名称与原始类中的方法或同一类(甚至超类)的另一个类别中的方法的名称相同,那么在运行时使用哪个方法实现就不定义行为。如果您在自己的类中使用类别,这不大可能成为问题,但是在使用类别向标准Cocoa或Cocoa Touch类添加方法时,这可能会导致问题。

It's Apple using a lighter touch, but the main point is the same: you invite disaster, because the unpredictable behavior is silent.

这是苹果公司(Apple)使用的一种更轻的触控方式,但其主旨是相同的:你会招致灾难,因为不可预知的行为是无声的。

#4


1  

It’s important to note that a category can also be used to override existing methods in the base class (e.g., the Car class’s drive method), but you should never do this. The problem is that categories are a flat organizational structure. If you override an existing method in Car+Maintenance.m, and then decide you want to change its behavior again with another category, there is no way for Objective-C to know which implementation to use. Subclassing is almost always a better option in such a situation.

需要注意的是,类别也可以用来覆盖基类中的现有方法(例如,Car类的drive方法),但您不应该这样做。问题是类别是一种扁平的组织结构。如果您重写了Car+维护中的现有方法。m,然后决定用另一个类别改变它的行为,Objective-C无法知道使用哪个实现。在这种情况下,子类化几乎总是更好的选择。

From this tutorial, http://rypress.com/tutorials/objective-c/categories

从本教程中,http://rypress.com/tutorials/objective-c/categories

#1


136  

From Apple documentation:

从苹果公司文档:

Although the Objective-C language currently allows you to use a category to override methods the class inherits, or even methods declared in the class interface, you are strongly discouraged from doing so. A category is not a substitute for a subclass. There are several significant shortcomings to using a category to override methods:

尽管Objective-C语言目前允许您使用一个类别来覆盖类继承的方法,甚至是类接口中声明的方法,但是强烈建议您不要这样做。类别不是子类的替代品。使用类别覆盖方法有几个明显的缺点:

  • When a category overrides an inherited method, the method in the category can, as usual, invoke the inherited implementation via a message to super. However, if a category overrides a method that exists in the category's class, there is no way to invoke the original implementation.

    当类别重写继承的方法时,类别中的方法通常可以通过消息调用继承的实现到super。但是,如果一个类别覆盖了类中存在的方法,那么就没有办法调用原始实现。

  • A category cannot reliably override methods declared in another category of the same class.

    类别不能可靠地覆盖在同一类的另一个类别中声明的方法。

    This issue is of particular significance because many of the Cocoa classes are implemented using categories. A framework-defined method you try to override may itself have been implemented in a category, and so which implementation takes precedence is not defined.

    这个问题特别重要,因为许多Cocoa类都是使用类别来实现的。您试图覆盖的框架定义方法本身可能已经在一个类别中实现,因此没有定义哪个实现优先级。

  • The very presence of some category methods may cause behavior changes across all frameworks. For example, if you override the windowWillClose: delegate method in a category on NSObject, all window delegates in your program then respond using the category method; the behavior of all your instances of NSWindow may change. Categories you add on a framework class may cause mysterious changes in behavior and lead to crashes.

    某些类别方法的存在可能会导致所有框架的行为变化。例如,如果重写NSObject上类别中的windowWillClose: delegate方法,则程序中的所有窗口委托使用category方法进行响应;所有NSWindow实例的行为都可能改变。在框架类中添加的类别可能会导致行为的神秘变化并导致崩溃。

#2


18  

You can do this by adapting Class Cluster approach, or using methods swizzling technique.

您可以通过采用类集群方法或使用方法swizzle技术来实现这一点。

Otherwise, the behavior of two or more categorized methods is undefined

否则,两个或多个分类方法的行为就没有定义

#3


8  

Old documentation link is dead; best replacement I could find was here: Apple Docs:

旧的文档链接已经失效;我能找到的最佳替代品是:苹果文档:

Avoid Category Method Name *es

Because the methods declared in a category are added to an existing class, you need to be very careful about method names.

因为在类中声明的方法被添加到一个现有类中,所以您需要非常注意方法名称。

If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime. This is less likely to be an issue if you’re using categories with your own classes, but can cause problems when using categories to add methods to standard Cocoa or Cocoa Touch classes.

如果在类别中声明的方法的名称与原始类中的方法或同一类(甚至超类)的另一个类别中的方法的名称相同,那么在运行时使用哪个方法实现就不定义行为。如果您在自己的类中使用类别,这不大可能成为问题,但是在使用类别向标准Cocoa或Cocoa Touch类添加方法时,这可能会导致问题。

It's Apple using a lighter touch, but the main point is the same: you invite disaster, because the unpredictable behavior is silent.

这是苹果公司(Apple)使用的一种更轻的触控方式,但其主旨是相同的:你会招致灾难,因为不可预知的行为是无声的。

#4


1  

It’s important to note that a category can also be used to override existing methods in the base class (e.g., the Car class’s drive method), but you should never do this. The problem is that categories are a flat organizational structure. If you override an existing method in Car+Maintenance.m, and then decide you want to change its behavior again with another category, there is no way for Objective-C to know which implementation to use. Subclassing is almost always a better option in such a situation.

需要注意的是,类别也可以用来覆盖基类中的现有方法(例如,Car类的drive方法),但您不应该这样做。问题是类别是一种扁平的组织结构。如果您重写了Car+维护中的现有方法。m,然后决定用另一个类别改变它的行为,Objective-C无法知道使用哪个实现。在这种情况下,子类化几乎总是更好的选择。

From this tutorial, http://rypress.com/tutorials/objective-c/categories

从本教程中,http://rypress.com/tutorials/objective-c/categories