Objective C 中的类别是如何实现的?

Posted

技术标签:

【中文标题】Objective C 中的类别是如何实现的?【英文标题】:How are categories implemented in Objective C? 【发布时间】:2011-08-11 12:57:29 【问题描述】:

作为程序员,我知道如何使用类别,但我很好奇它们是如何实现的。编译器是否将它们编译为从静态初始化程序对class_replaceMethod 的调用?谢谢。

【问题讨论】:

【参考方案1】:

关于主题的新答案。

每个类都有一个方法列表,在进行方法查找时,方法列表会从头到尾扫描。如果没有找到方法,则扫描超类的列表等,直到到达根类。缓存找到的方法以便下次更快查找。

当将类别加载到类中时,类别方法列表会添加到现有列表中,并且缓存会被刷新。由于列表是按顺序搜索的,这意味着类别方法将在下一次搜索时原始方法之前找到。

这种类别的设置是在第一次访问类时从静态数据中懒惰地完成的。如果加载带有可执行代码的包,则可以重新完成。

总之比class_replaceMethod()低一点。

【讨论】:

在第一次使用类别之前,是否有一个“初始化”类别的好地方?我试过+initialize,但它似乎在第一次调用类别类时就被调用了,所以初始化类别可能是不必要的,更重要的是,可能会导致无限循环。【参考方案2】:

您可以从这里找到所有您想知道的关于它们如何工作的信息。

http://opensource.apple.com/source/objc4/objc4-493.9/runtime/objc-runtime-new.mm

运行时完全开源。

【讨论】:

谢谢,这很有用。我希望我能接受多个答案,所以我将只支持您的评论。【参考方案3】:

类别没有任何特殊的实现,它们实际上本质上是没有实现的。

协议在运行时充当类的标记。您可以使用class_copyProtocolList() 从运行时获取类符合的协议列表。有一个兄弟protocol_copyProtocolList()函数来获取一个协议所遵循的协议。

请注意,这些方法仅返回此特定类或协议的协议列表。不是来自超类或其他协议的引用。这意味着在运行时的实际查找会很昂贵。而是使用class_conformsToProtocol()(或protocol_conformsToProtocol()来查询一致性,这些方法可以缓存结果。

实际上,在运行时查询一致性很少是一个好主意。协议一致性由编译器通过警告来验证,如果开发人员选择忽略这些警告,那么......这是他们的选择。

【讨论】:

你为什么要谈论协议?它们与类别完全不同? @Joshua Weinberg - 没错,我完全把自己搞砸了。我 100% 确定问题是协议。该死,在正确的情况下,我会喜欢我的答案。

以上是关于Objective C 中的类别是如何实现的?的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C如何声明类别的私有财产?

在 Objective-C 中使用类别的私有方法:从子类调用 super

如何在 Swift 中调用 Objective-C 类别方法

如何在iOS,Objective C的tableview中的每个部分中仅实现单个单元格选择

浅谈Swift 2中的Objective-C指针

Objective C 类别 vs 开放/封闭原则