为什么类别不能包含实例变量?

时间:2014-01-10 03:24:44

标签: objective-c objective-c-category ivar

我知道我们可以使用关联引用来调用类别中的类似ivar的行为。但是,无法在类别中声明新的ivars背后的具体原因是什么?

是因为我们会入侵班级的私人空间吗?或者还有其他原因吗?如果是的话,我会很感激一个例子,它显示了在类别中声明ivars的能力,可以打破它所破坏的任何内容。

1 个答案:

答案 0 :(得分:25)

将Objective-C的ivars想象成一个普通的旧C结构。当您实例化一个类的实例时,会创建一个足够大的内存块来保存该结构。

假设你有NSString。编译了大量现有代码以使用NSString。很多代码都内置在库和框架中。已编译的代码是在知道NSString的ivars占用X个字节并且在该内存中的某些给定偏移量的情况下创建的。

现在在您自己的小项目中,我们假设您在NSString上创建了一个类别,并希望添加一个ivar。理论上,项目中包含该类别头文件的任何代码都知道此“新”NSString(加类别)的大小需要X + Y字节。这很像一个子类。这个新编译的代码可以正确处理额外的ivar。

但是所有预编译的代码,库和框架都不会知道额外的ivars。当在那里创建NSString个实例时,内存只有X个字节,而不是X + Y个字节。随着您的应用程序代码获取对该较小内存块的引用并尝试访问类别ivar的字节,随之发生混乱。事情会好转。

使用一个普通的旧子类,事情可行,因为任何可以使用子类'ivars的代码都知道子类的ivars。但是对于一个类别,预先存在的代码不知道添加内容,也不会为它们正确创建空间。

我想我应该指出以上所有内容都是一个有根据的猜测。我完全错了。这似乎至少是合理的。 :)