如果某個(gè)存儲(chǔ)型屬性的默認(rèn)值需要特別的定制或準(zhǔn)備,你就可以使用閉包或全局函數(shù)來為其屬性提供定制的默認(rèn)值。每當(dāng)某個(gè)屬性所屬的新類型實(shí)例創(chuàng)建時(shí),對(duì)應(yīng)的閉包或函數(shù)會(huì)被調(diào)用,而它們的返回值會(huì)當(dāng)做默認(rèn)值賦值給這個(gè)屬性。
這種類型的閉包或函數(shù)一般會(huì)創(chuàng)建一個(gè)跟屬性類型相同的臨時(shí)變量,然后修改它的值以滿足預(yù)期的初始狀態(tài),最后將這個(gè)臨時(shí)變量的值作為屬性的默認(rèn)值進(jìn)行返回。
下面列舉了閉包如何提供默認(rèn)值的代碼概要:
class SomeClass {
let someProperty: SomeType = {
// 在這個(gè)閉包中給 someProperty 創(chuàng)建一個(gè)默認(rèn)值
// someValue 必須和 SomeType 類型相同
return someValue
}()
}
注意閉包結(jié)尾的大括號(hào)后面接了一對(duì)空的小括號(hào)。這是用來告訴 Swift 需要立刻執(zhí)行此閉包。如果你忽略了這對(duì)括號(hào),相當(dāng)于是將閉包本身作為值賦值給了屬性,而不是將閉包的返回值賦值給屬性。
注意:
如果你使用閉包來初始化屬性的值,請(qǐng)記住在閉包執(zhí)行時(shí),實(shí)例的其它部分都還沒有初始化。這意味著你不能夠在閉包里訪問其它的屬性,就算這個(gè)屬性有默認(rèn)值也不允許。同樣,你也不能使用隱式的self
屬性,或者調(diào)用其它的實(shí)例方法。
下面例子中定義了一個(gè)結(jié)構(gòu)體Checkerboard
,它構(gòu)建了西洋跳棋游戲的棋盤:
西洋跳棋游戲在一副黑白格交替的 10x10 的棋盤中進(jìn)行。為了呈現(xiàn)這副游戲棋盤,Checkerboard
結(jié)構(gòu)體定義了一個(gè)屬性boardColors
,它是一個(gè)包含 100 個(gè)布爾值的數(shù)組。數(shù)組中的某元素布爾值為true
表示對(duì)應(yīng)的是一個(gè)黑格,布爾值為false
表示對(duì)應(yīng)的是一個(gè)白格。數(shù)組中第一個(gè)元素代表棋盤上左上角的格子,最后一個(gè)元素代表棋盤上右下角的格子。
boardColor
數(shù)組是通過一個(gè)閉包來初始化和組裝顏色值的:
struct Checkerboard {
let boardColors: Bool[] = {
var temporaryBoard = Bool[]()
var isBlack = false
for i in 1...10 {
for j in 1...10 {
temporaryBoard.append(isBlack)
isBlack = !isBlack
}
isBlack = !isBlack
}
return temporaryBoard
}()
func squareIsBlackAtRow(row: Int, column: Int) -> Bool {
return boardColors[(row * 10) + column]
}
}
每當(dāng)一個(gè)新的Checkerboard
實(shí)例創(chuàng)建時(shí),對(duì)應(yīng)的賦值閉包會(huì)執(zhí)行,一系列顏色值會(huì)被計(jì)算出來作為默認(rèn)值賦值給boardColors
。上面例子中描述的閉包將計(jì)算出棋盤中每個(gè)格子合適的顏色,將這些顏色值保存到一個(gè)臨時(shí)數(shù)組temporaryBoard
中,并在構(gòu)建完成時(shí)將此數(shù)組作為閉包返回值返回。這個(gè)返回的值將保存到boardColors
中,并可以通squareIsBlackAtRow
這個(gè)工具函數(shù)來查詢。
let board = Checkerboard()
println(board.squareIsBlackAtRow(0, column: 1))
// 輸出 "true"
println(board.squareIsBlackAtRow(9, column: 9))
// 輸出 "false"