【问题标题】:Overriding computed property with stored one用存储的一个覆盖计算属性
【发布时间】:2018-03-22 11:11:07
【问题描述】:

假设我有这样的 A 和 B 类:

class A {
    var x: Int { return 9 }
    func p() {  print(x) }
}

class B: A {
    ...
}

let v: A = B()
v.p()

然后我以三种不同的方式覆盖 B 中的 x:

class B: A {

    // OPTION 1: FINE - prints 10
    override var x: Int { return 10 }

    // OPTION 2: ERROR - cannot override with a stored property 'x'
    override var x = 10

    // OPTION 3: FINE - prints 10
    override lazy var x = 10

}

有人能解释一下用存储属性覆盖计算属性有什么问题吗?为什么当我声明它是惰性的时一切都突然修复了?

【问题讨论】:

    标签: swift properties


    【解决方案1】:

    您不能用存储的属性覆盖属性并没有真正的技术原因;它有getter和setter(访问器),可以覆盖要覆盖的属性的访问器。它应该等同于用计算属性覆盖,然后转发到存储属性。

    不过,我确实预见到允许这样做的一个小麻烦:属性观察者覆盖。

    考虑以下示例:

    class C {
      var f: Int {
        get { return 5 }
        set { print("C says f was set") }
      }
    }
    
    class D : C {
      override var f: Int {
        didSet {
          print("D says f was set")
        }
      }
    }
    
    let d = D()
    print(d.f)
    d.f = 7
    print(d.f)
    
    // 5
    // C says f was set
    // D says f was set
    // 5
    

    我们可以在D 中覆盖fdidSet。在这种情况下,override var f: Int 本质上被视为具有 getter 和 setter 的计算属性,它们转发到 super,并在 setter 中额外调用 didSet 实现。

    D 这里没有介绍实际的存储。那么为什么会有问题呢?那么,我们如何告诉编译器我们确实确实想要为f 存储空间?添加初始化表达式 (= 10) 可以传达这一点,但并非所有存储的属性都有默认值;大多数都是从类的指定初始化程序中初始化的。我们可能需要某种属性,但对于这样一个有限的用例,这似乎不是对语言的特别有用的更改。

    lazy 的情况很明确,因为我们无法向它们添加属性观察者。

    虽然说了这么多,但你提出的具体案例应该是明确的;由于基本属性只有一个 getter,所以没有要覆盖的属性观察者。我会推荐你​​file a bug(希望)看看 Swift 团队对此有何看法。

    您始终可以通过计算属性覆盖实现相同的结果,然后将其转发到存储属性:

    class C {
      var f: Int {
        return 9
      }
    }
    
    class D : C {
    
      private var _f: Int = 10
    
      override var f: Int {
        get { return _f }
        set { _f  = newValue }
      }
    }
    
    let d = D()
    print(d.f) // 10
    d.f = 7
    print(d.f) // 7
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-11
      • 1970-01-01
      • 2016-10-28
      相关资源
      最近更新 更多