使用Objective-C中的类别覆盖方法

时间:2011-03-11 11:42:36

标签: objective-c categories

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

1)原始方法

-(BOOL) method {
  return true;
}

2)覆盖方法

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

这会起作用,还是非法的?

4 个答案:

答案 0 :(得分:142)

来自Apple documentation

  

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

     
      
  • 当某个类别覆盖继承的类别时   方法,类别中的方法   像往常一样,可以调用继承的   通过消息实现super。   但是,如果某个类别覆盖了   类别中存在的方法   类,没有办法调用   原始实施

  •   
  • 类别无法可靠地覆盖在同一类别的其他类别中声明的方法。

         

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

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

  •   

答案 1 :(得分:18)

您可以通过调整Class Cluster方法或使用methods swizzling技术来实现此目的。

否则,两个或多个分类的方法的行为是undefined

答案 2 :(得分:8)

旧的文档链接已经死了;我能找到的最佳替代品是:Apple Docs

  

避免使用类别方法名称冲突

     

因为在类别中声明的方法被添加到现有类中,所以需要非常小心方法名称。

     

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

这是苹果使用更轻松的触摸,但重点是相同的:你邀请灾难,因为不可预知的行为是沉默的。

答案 3 :(得分:2)

重要的是要注意,类别也可以用于覆盖基类中的现有方法(例如,Car类的驱动方法),但是你永远不应该这样做。问题是类别是一个扁平的组织结构。如果您覆盖Car + Maintenance.m中的现有方法,然后决定要再次使用其他类别更改其行为,则Objective-C无法知道要使用哪个实现。在这种情况下,子类化几乎总是更好的选择。

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