为什么目标C不支持私有方法?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (15)

我已经看到了许多策略来声明半私有方法目标-C,但似乎没有办法使一个真正的私人方法

有一些关键字应用于ivars(成员)控制其范围的成员,如@private@public@protected。为什么不能用同样的方法来实现呢?

提问于
用户回答回答于

目的C在方法调度时是纯动态的。特别是,每个方法调度都会经历与其他方法调度完全相同的动态方法解析点。在运行时,每个方法实现都有完全相同的公开,与方法和选择器一起工作的Object-C运行时提供的所有API在所有方法之间都是一样的。

编译时私有方法是受支持的;如果一个类没有在其公开可用的接口中声明一个方法,那么就代码而言,该方法可能不存在。换句话说,可以通过适当地组织项目来实现编译时所需的所有不同的可见性组合。

将相同的功能复制到运行时几乎没有好处。这将增加巨大的复杂性和开销。即使有这么多的复杂性,它也不会阻止所有的开发人员执行您所谓的“私有”方法,但最随意的开发人员除外。

编辑:我注意到的一个假设是,私有消息必须经过运行时,从而产生潜在的巨大开销。这绝对是真的吗? 是的,是的。没有理由假设类的实现者不希望在实现中使用所有的Object-C特性集,这意味着必须进行动态分派。不过的特殊变体无法分派私有方法的原因。objc_msgSend(),因为编译器知道它们是私有的;也就是说,这可以通过向Class结构。没有办法让私人的方法短路这个检查或跳过运行时? 它不能跳过运行时,但是运行时不会必须对私有方法进行任何检查。 也就是说,没有理由不让第三方故意打电话objc_msgSendPrivate()在对象上,在该对象的实现之外,有些事情(例如,KVO)必须这样做。实际上,它只是一种惯例,在实践中比在接口头中前缀私有方法的选择器或不提及它们更好。

然而,这样做会破坏语言纯粹的动态性质。不再是每个方法调度都经过相同的调度机制。相反,可能会遇到这样的情况:大多数方法的行为方式都是单一的,而少数方法只是不同的。

这超出了运行时的范围,因为Cocoa中有许多机制建立在Object-C的一致动态之上。例如,键值编码和键值观测要么必须经过很大的修改才能支持私有方法--最有可能是通过创建可利用的漏洞--要么私有方法将不兼容。

用户回答回答于

运行时可以支持它,但代价将是巨大的。每个发送的选择器都需要检查它是私有的还是公共的,或者每个类都需要管理两个单独的调度表。这与实例变量不同,因为这个级别的保护是在编译时完成的。

此外,运行时还需要验证私有消息的发送方是否与接收方属于同一类。还可以绕过私有方法;如果类使用instanceMethodForSelector:,它可以给返回的IMP直接调用私有方法的任何其他类。

私有方法无法绕过消息分发。考虑以下情况:

  1. 一堂课AllPublic具有公共实例方法doSomething
  2. 另一类HasPrivate具有一个私有实例方法(也称为doSomething
  3. 创建一个数组,该数组包含两个实例的任意数量。AllPublicHasPrivate
  4. 您有以下循环: 用于(myArray中的id和Object)一种客观的方法; 如果你从内部运行那个循环AllPublic,运行时必须停止发送doSomethingHasPrivate实例,但是,如果该循环位于HasPrivate上课。

扫码关注云+社区