// 定義
fun alphabet(): String {
val result = StringBuilder()
for(letter in 'A' .. 'Z') {
result.append(letter)
}
result.append("\nNow I know the alphabet!")
return result.toString()
}
// 測試
>>> println(alphabet())
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Now I know the alphabet!
複製代碼
上述例子中,調用result實例上好幾個不一樣的方法,並且每次調用都要重複result這個名稱。若實例名比較長,就比較糟糕!markdown
with
***構造字母表fun alphabet(): String {
val stringBuilder = StringBuilder()
// 指定接受者的值,你會調用它的方法
return with(stringBuilder) {
for(letter in 'A' .. 'Z') {
// 經過顯式的「this」來調用接受者值的方法
this.append(letter)
}
// 省略「this」也能夠調用方法
append("\nNow I know the alphabet!")
// 從lambda返回值
this.toString()
}
}
複製代碼
with
結構看起來像是一種特殊的語法結構,但它其實是一個接受兩個參數的函數:這個例子中兩個參數分別是stringBuilder和一個lambda。這裏利用了把lambda放在括號外的約定,這樣整個調用看起來就像是內建的語言功能。固然也能夠把它寫成*with(stringBuilder, { ... })
***,但可讀性就會差不少。app
with函數把它的第一個參數轉換成做爲第二個參數傳給它的lambda的接受者。能夠顯示地經過this引用來訪問這個接受者。或者,按照慣例,能夠省略this引用,不用任何限定符直接訪問這個值的方法和屬性。函數
fun alphabet() = with(StringBuilder()) {
for(letter in 'A' .. 'Z') {
append(letter)
}
append("\nNow I know the alphabet!")
toString()
}
複製代碼
如今這個函數只返回一個表達式,因此使用表達式函數體語法重寫了它。能夠建立一個新的StringBuilder實例直接看成實參傳給這個函數,而後在lambda中不須要顯示的this就能夠引用這個實例。測試
注意:
with
返回的值是執行lambda代碼的結果,該結果就是lambda中的最後一個表達式(的值)**。ui
apply
*函數幾乎和with函數如出一轍,惟一的區別是**apply
始終會返回做爲實參傳遞給它的對象*(換句話說,接受者對象)。this
fun alphabet() = StringBuilder().apply {
for(letter in 'A' .. 'Z')
append(letter)
append("\nNow I know the alphabet!")
}.toString()
複製代碼
***apply
被聲明成一個擴展函數。它的接受者變成了做爲實參的lambda的接受者。執行apply
***的結果是StringBuilder,因此接下來你能夠調用toString把它轉換成String。spa
許多狀況下***apply
***都頗有效:code
apply
***,完成不須要任何來自自定義該對象的哭的特殊支持。fun createViewWithCustomAttributes(context: Context) =
TextView(context).apply {
text = "Sample Text"
textSize = 20.0F
setPadding(10, 0, 0, 0)
}
複製代碼