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