我知道我们可以使用关联引用在类别中调用类似 ivar 的行为。但是,无法在类别中声明新 ivars 的具体原因是什么?
是因为我们会侵犯班级的私人空间吗?还是有其他原因?如果是的话,我会很感激一个例子,它显示了在类别中声明 ivars 打破它打破的能力。
我知道我们可以使用关联引用在类别中调用类似 ivar 的行为。但是,无法在类别中声明新 ivars 的具体原因是什么?
是因为我们会侵犯班级的私人空间吗?还是有其他原因?如果是的话,我会很感激一个例子,它显示了在类别中声明 ivars 打破它打破的能力。
将 Objective-C 的 ivars 想象成一个普通的旧 C 结构。当您实例化一个类的实例时,会创建一个足够大的内存块来保存该结构。
假设您有一个NSString
. 大量现有代码被编译使用NSString
。很多这些代码都内置在库和框架中。该编译后的代码是在知道 ivarsNSString
占用 X 个字节并且在该内存中处于某些给定偏移量时创建的。
现在在您自己的小项目中,假设您创建了一个类别NSString
并想要添加一个 ivar。理论上,项目中包含该类别头文件的任何代码都会知道这个“新” NSString
(加上类别)的大小需要 X + Y 个字节。这很像一个子类。这个新编译的代码可以正确处理额外的 ivar。
但是所有预编译的代码,库和框架,都不知道额外的 ivars。当NSString
在那里创建实例时,内存只有 X 字节,而不是 X + Y 字节。当您的应用程序代码获得对较小内存块的引用并尝试访问类别 ivar 的字节时,就会出现混乱。事情会变得繁荣。
对于普通的旧子类,一切正常,因为任何可以使用子类的 ivars 的代码都知道子类的 ivars。但是对于一个类别,预先存在的代码不知道添加的内容,也不会为它们正确创建空间。
我想我应该说明以上所有内容在很大程度上都是有根据的猜测。我可能完全错了。至少看起来是合理的。:)