2015-10-14 87 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好,我的錯。我編輯了這篇文章來解決它。 –