如何使用getter / setter方法进行延迟初始化?

时间:2017-08-29 12:27:01

标签: ios swift getter-setter lazy-initialization

如何使用getset()闭包进行延迟初始化。

这是懒惰的初始化代码:

lazy var pi: Double = {
        // Calculations...
        return resultOfCalculation
        }()

这里是getter / setter代码:

var pi: Double {
    get {
        //code to execute
        return someValue
    }
    set(newValue) {
        //code to execute
    }
}

2 个答案:

答案 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 是惰性的。

总的来说,这个问题毫无意义。 (短语"我如何使用延迟初始化"揭示了这个缺陷,因为计算出的变量从未初始化 - 它被计算出来!)