2015-10-14 68 views
4

在这个article中,它说(引用下面的代码):“您必须使用lazy来防止闭包被多次创建。”带闭包的懒惰变量

private lazy var variable:SomeClass = { 
    let fVariable = SomeClass() 
    fVariable.value = 10 
    return fVariable 
}() 

为什么懒惰会阻止多次创建闭包?为什么缺乏懒惰会导致它不止一次地评估?

+0

我的书中的解释更好:http://www.apeth.com/swiftBook/ch03。html#_lazy_initialization – matt

+0

谢谢 - 书的解释非常好。 – Boon

回答

12

你引用的教程代码是这样的:

private lazy var variable:SomeClass = { 
    let fVariable = SomeClass() 
    fVariable.value = 10 
    return fVariable 
}() 

与此对比吧:

private var variable:SomeClass { 
    let fVariable = SomeClass() 
    fVariable.value = 10 
    return fVariable 
} 

第一个初始化variable到新创建的SomeClass的实例,一次最多(和甚至可能没有那么多次)。第二个是只读计算变量,并在每次读取其值时创建一个新的SomeClass实例。

10

你的直觉是对的,那篇文章是不正确的。我猜测作者正在将计算出的属性语法与立即执行的关闭技巧混为一谈。 lazy关键字与关闭执行多少次无关。 lazy只是简单地导致该属性保持未初始化,直到第一次访问,此时评估等号右侧的表达式。

为了简化,此:

var myVar: MyType { 
    return MyType() 
} 

比这非常不同:

var myVar: MyType = MyType() 

这是在存储类似,但具有不同的初始化语义比这:

lazy var myVar: MyType = MyType() 

在第一个例子,myVar是一个计算属性和cu中的代码每次访问myVar时都会执行大括号。换句话说,每次访问myVar时,都会得到一个新创建的对象。

在第二个示例中,myVar是存储的属性,等号后面的表达式在包含该属性的类或结构的初始化过程中计算一次。

在第三个示例中,myVar仍然是一个存储属性,但在等号(不论是初始值设定表达式,函数调用还是闭包调用)之后,对表达式的求值将被延迟,直到它被访问。

作为一个侧面说明,这行代码:

lazy var myVar: MyType = { ... }() 

等同于:

func doStuffAndReturnMyType() { ... } 
lazy var myVar: MyType = doStuffAndReturnMyType() 

在第一个例子中的简写不是专门设计的,它只是工作,因为斯威夫特类型系统(非常棒),并将闭包视为未命名(匿名)函数。

+0

很清楚,谢谢。 – Boon

+1

我是否在这行中不需要拖尾括号'func doStuffAndReturnMyType(){...}()'? –

+1

@ShadowOf好,我的错。我编辑了这篇文章来解决它。 –