如何使用get
和set()
闭包进行延迟初始化。
这是懒惰的初始化代码:
lazy var pi: Double = {
// Calculations...
return resultOfCalculation
}()
这里是getter / setter代码:
var pi: Double {
get {
//code to execute
return someValue
}
set(newValue) {
//code to execute
}
}
答案 0 :(得分:2)
我假设你要做的是懒惰地为可写属性生成默认值。我常常发现人们在不需要时会跳到懒惰状态。确保这确实值得一试。如果很少使用默认值,这只会值得,但创建起来相当昂贵。但如果这是你的情况,这是一种方法。
lazy
实现了一个非常具体且相当有限的模式,通常不是你想要的。 (根本不清楚lazy
是语言的一个有价值的补充因为它是如何工作的,并且正在积极地用更强大和有用的属性系统替换它。)lazy
不是你想要的工具,你只需建立自己的工具。在您的示例中,它看起来像这样:
private var _pi: Double?
var pi: Double {
get {
if let pi = _pi { return pi }
let result = // calculations....
_pi = result
return result
}
set { _pi = newValue }
}
这就是说,在我见过这种情况的大多数情况下,最好在init中使用默认值:
func computePi() -> Double {
// compute and return value
}
// This is global. Globals are lazy (in a thread-safe way) automatically.
let computedPi = computePi()
struct X {
let pi: Double // I'm assuming it was var only because it might be overridden
init(pi: Double = computedPi) {
self.pi = pi
}
}
这样做只能在整个程序中计算一次pi(而不是每个实例一次)。它让我们让pi
“写一次完全”而不是可变状态。 (这可能会或可能不符合您的需求;如果它确实需要可写,那么var
。)
类似的默认值方法可用于构造成本高的对象(而不是计算成本高昂的静态事物),而不需要全局。
struct X {
let pi: Double
init(pi: ExpensiveObject = ExpensiveObject()) {
self.pi = pi
}
}
但有时候,吸气剂和制定者更适合。
答案 1 :(得分:1)
lazy
变量的要点是它在被提取之前不会被初始化,从而阻止它(可能是昂贵的)初始化程序运行,直到除非访问该变量的值。
嗯,这正是计算变量的吸气剂也是如此!除非被调用,否则它不会运行。因此,计算变量的getter 是惰性的。
总的来说,这个问题毫无意义。 (短语"我如何使用延迟初始化"揭示了这个缺陷,因为计算出的变量从未初始化 - 它被计算出来!)