【问题标题】:Why I should access the instance variable directly from within an initialization method?为什么我应该直接从初始化方法中访问实例变量?
【发布时间】:2013-07-17 14:56:24
【问题描述】:

Apple Programming with Objective-C 文件指出:

您应该始终直接从内部访问实例变量 初始化方法,因为在设置属性时, 对象的其余部分可能尚未完全初始化。即使你 不要提供自定义访问器方法或知道任何副作用 在你自己的类中,未来的子类很可能会覆盖 行为。

但我不知道在setter方法中会有什么副作用,请给我一个例子来解释为什么我必须直接从初始化方法中访问实例变量

【问题讨论】:

    标签: ios objective-c


    【解决方案1】:

    答案很简单——就是代码异味。像 Objective-C 中的 self.foobar = something 这样的点符号只是消息传递的语法糖。 向self 发送消息通常没问题。但是有两种情况你需要避免它们:

    1。创建对象时,以及

    2。当对象被销毁时。

    在这两次,对象处于一种奇怪的中间状态。它缺乏完整性。在这些时间调用方法是一种代码异味,因为每个方法在对对象进行操作时都应保持不变量。

    【讨论】:

      【解决方案2】:

      如果一个 setter 方法被子类覆盖,您无法保证您的实例变量将包含正确的数据。如果您想在初始化等关键阶段保持对象内的数据完整性,您应该按照 Apple 的建议进行操作。

      【讨论】:

      • 但是如果子类想要限制一些值怎么办。就像确保整数小于 1000 一样。子类可能依赖于此,如果您直接在父类的 init 中设置实例变量,您可能会破坏子类中的其他功能。您可能没有真正的理由(除了整数限制)来覆盖父级的init。如果您设置该属性,那么您将控制权交还给子类(谁应该真正拥有它)。
      • @Firo 子类应该覆盖超类'init。从对象生命周期的角度考虑这一点。在某些阶段应调用某些方法。在初始化期间,对象在任何时候都不能被认为是完全初始化的;因此,我们不应该调用仅在对象 完全初始化时才调用的 setter 方法。
      • 我猜,看起来你最终会得到重复的代码(在超类的init 中设置值,在子类的init 中设置和检查它,并检查和设置它在属性设置器中)。对我来说似乎很奇怪和多余。虽然可能是必要的。
      • 如果您的 init 方法需要 setter 中的逻辑来验证状态,那么您手头上还有一大堆其他问题...
      【解决方案3】:

      除了@JacobRelkin 点,副作用还可以包括键值观察。即使在-init*-dealloc 期间,其他对象也可以观察到变化。我过去遇到过 KVO -dealloc 错误。

      直接设置和拆除 ivars 确实是最佳实践。

      【讨论】:

      • 在调用上下文存储来自-init的返回值之前,其他对象如何进行KVO-ing?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-06
      • 2011-03-18
      • 1970-01-01
      • 2016-02-14
      • 1970-01-01
      相关资源
      最近更新 更多