为什么当它们和它们的访问器方法都没有被合成时,允许在类别中声明属性?是否涉及任何性能开销?
分类纯粹是编译器技术吗?
我试图了解类别的工作原理。 This只是解释了做什么和不做什么。有没有更详细的消息来源?
编辑:我知道我可以使用关联的引用。这不是我要求的。我想知道为什么这些属性没有合成?如果编译器合成它们,是否存在性能问题或安全问题?如果有,我想知道什么和如何?
答案 0 :(得分:2)
在进入类别之前,请重新考虑Obj-C中的属性概念:属性是您可以使用访问器以抽象的方式编写和读取的内容。通常,会为其分配一个实例变量,但不需要这样做。 一个属性也可能是有用的,例如,以一致的方式设置多个不同的实例变量,或从多个变量中读取或进行一些计算。
这里的关键事实是:不需要为属性分配实例变量。
类别用作对象行为的扩展,即扩展其方法集,而不更改数据。如果你看到一个抽象意义上的属性,那么它会添加访问器,因此它匹配一个类别的想法。 但是如果你合成它,就会产生一个与类别概念相矛盾的实例变量。
因此,如果你以一种不常见的抽象方式使用它,那么一个类别中的属性才有意义,@synthesize
是为了简化常用方法。
答案 1 :(得分:2)
为什么允许在类别[...]中声明属性?
属性有很多方面(在编译和运行时)。
在类别(或协议)中声明属性并且无法进行合成时,大多数这些方面仍然有用。
分类纯粹是编译器技术吗?
没有。作为属性的类别既有编译时间也有运行时方面。
例如,类别可以在以后从动态库加载。因此,可能已经有一个类的实例突然添加了新方法。这是类别无法添加ivars的原因之一,因为旧对象会丢失这些ivars以及运行时如何判断是否在添加类别之前或之后创建了对象。
答案 2 :(得分:0)
您可能需要阅读NSHipster,了解如何在类别中实施属性存储。
引用文章:“为什么这有用?它允许开发人员在类别中向现有类添加自定义属性,这是Objective-C的一个明显缺点。”
答案 3 :(得分:0)
@synthesize
通知编译器继续并为setter和getter提供默认实现。
表示默认的setter / getters依赖于对象内存在某种存储。
类别不提供任何额外的存储空间,因此默认的setter / getter将没有 place 存储或读取。
另一种方法是使用:
@dynamic
然后为所述属性提供您自己的实现和自己的存储。
一种方法是使用关联对象。 另一种方法是存储/读取一些完全不相关的地方,例如一些可访问的NSUserDefaults字典或...
在某些情况下,对于只读属性,您还可以在运行时重建/计算它们的值,而无需存储它们。