在Objective C中定义不可变类的最佳方法

Pat*_*rty 17 objective-c immutability

我是Objective C的新手,我想知道在Objective-C中定义不可变类的最佳方法是什么(比如NSString).

我想知道为了使类不可变,必须遵循的基本规则是什么.

我觉得 :

  • 不应该提供塞特犬
  • 如果使用属性,它们应该是只读的
  • 要"禁用"键值编码,accessInstanceVariablesDirectly必须覆盖并返回NO

我忘记了什么吗?

谢谢

Rob*_*ier 13

您应该做的首要事情是在.h文件中包含用法注释,以解释这是一个不可变类,以及类的用途和一般用法指南.很多时候人们会竭尽全力尝试用编译器"强制执行",只需告知调用者即可实现.

如果你打算让类不可变,你当然不应该提供公共setter或readwrite属性(当然你应该提供私有的setter,以便你可以在类中使用访问器;你应该总是避免,甚至在内部,直接搞乱ivars除外在一些地方).我猜你可以添加你的accessInstanceVariablesDirectly覆盖,如果你看到这可能是调用者的错误.

但理解Objective-C的关键是理解并接受呼叫者不是敌人的事实.被调用的代码不需要被调用者"保护".需要保护呼叫者免受可能的错误.每个人都站在同一边; 调用者和被调用者希望程序正常工作.

呼叫者是客户,应该这样对待.客户并不总是正确的,但客户始终是客户.有时这意味着如果他可能犯的一个容易的错误,保护客户免受他自己的伤害.NSAssert()对此特别有用.将公共设置者提供给不可变的类几乎是欺骗调用者犯错误,这对每个人都是坏事.

无论如何,你不应该让你的班级过于复杂以试图强制执行不变性.调用者几乎(*)总是通过直接访问struct(object->ivar)来违反封装.打电话的人这样做是愚蠢的,但你试图阻止它会更加愚蠢.注意不变性,隐藏你的二传手并只读标记你的属性,几乎在所有情况下你应该没事.

(*)是的,通过将私有结构/对象嵌套为ivar,可以更隐藏数据,但是调用者仍然可以使用指针算法修改数据,因此它仍然没有"强制执行".总是问问自己,你真正想要解决的问题是什么.

  • 绝对.强制单身人士(覆盖+ allocWithZone :)几乎总是一个错误,弊大于利.唯一有意义的地方是,如果你*希望*使单身性质成为私人实施细节.否则,您通常应该使用允许多个实例的"共享单例"模式,或者您应该使用NSAssert()将第二个实例创建为编程错误. (2认同)

Fra*_*k V 6

我相信他们实现这一目标的方法是让头文件只包含公开所需的信息.其余的将进入源文件以限制可能的覆盖曝光.

由于Objective-C显然没有明确的方法来定义一个类作为final(密封等),所以你能做的一切并不是真的包罗万象.

我很久以前得出结论,你真的不能使用Objective-C,就像你使用Java,C++或C#一样.Objective-C太不同了.事实上,我认为存在严重的范式差异,例如静态与动态方法调度/调用.

我提到这个的原因是因为Objective-C中的类可能不是真正的最终类.也许这是通过语言设计而不是你应该试图绕过的东西.如果你这样做,你最终会不必要地使你的代码复杂化.