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


87

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

1)原始方法

-(BOOL) method {
  return true;
}

2)覆盖方法

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

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

Answers:


146

Apple文档

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

  • 当类别覆盖继承的方法时,该类别中的方法可以照常通过到的消息来调用继承的实现super。但是,如果类别覆盖了该类别的类中存在的方法,则无法调用原始实现

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

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

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


谢谢,但我已经知道了。我只是想知道我的案子是否合法。我的案子与文件有所不同。:)
retix

为什么与众不同?该文档说,如果原始方法不在类别中,但强烈建议不要这样做,那是合法的。然后,您可以做...
贝诺

1
谢谢你的建议。我的语言不好。我收到了你的新消息。
retix 2011年

1
在超类的Category中声明和实现的Category方法中重写是否正确?
BergP 2013年



9

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

避免类别方法名称冲突

由于在类别中声明的方法已添加到现有类中,因此您需要非常小心方法名称。

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

苹果使用的是轻巧的触摸,但要点是一样的:您招致灾难,因为无法预测的行为是无声的。


2

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.