gpt4 book ai didi

swift - 用存储的属性覆盖计算属性

转载 作者:搜寻专家 更新时间:2023-11-01 07:08:21 24 4
gpt4 key购买 nike

假设我有一个像这样的 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

}

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

最佳答案

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

但是我确实预见到允许这样做会带来一点复杂的情况:属性观察者覆盖。

考虑以下示例:

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 本质上被视为具有转发到 super 的 getter 和 setter 的计算属性,并额外调用了 didSet 在 setter 中实现。

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

lazy 情况很明确,因为我们不能向它们添加属性观察器。

尽管如此,您提出的具体案例也应该一目了然;因为基础属性只有一个 setter/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

关于swift - 用存储的属性覆盖计算属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46676992/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com