2017-08-31 174 views

回答

26

所有這些函數都用於切換當前函數/變量的作用域。它們被用來將所有屬於同一個地方的東西(主要是初始化)保存在一起。

下面是一些例子:

run - 返回你想和重新作用域它的上this

val password: Password = PasswordGenerator().run { 
     seed = "someString" 
     hash = {s -> someHash(s)} 
     hashRepetitions = 1000 

     generate() 
    } 

密碼生成器現在rescoped爲this使用變量任何東西,因此我們可以設置seedhashhashRepetitions而不使用變量。 generate()將返回Password的實例。

apply是相似的,但它會返回this

val generator = PasswordGenerator().apply { 
     seed = "someString" 
     hash = {s -> someHash(s)} 
     hashRepetitions = 1000 
    } 
val pasword = generator.generate() 

這是作爲Builder模式的替代品特別有用,如果你想重新使用某些配置。

let - 主要用於避免空檢查,但也可以用作run的替代品。所不同的是,this仍然會像以前一樣,你訪問使用it重新範圍的變量:

val fruitBasket = ... 

apple?.let { 
    println("adding a ${it.color} apple!") 
    fruitBasket.add(it) 
} 

上面的代碼將蘋果添加到購物籃只有當它不爲空。還要注意的是it現在不是可有可無的了所以你不會碰到一個NullPointerException這裏(又名你不需要使用?.來訪問它的屬性。)

also - 當你想用用它apply,但不想陰影this

class FruitBasket { 
    private var weight = 0 

    fun addFrom(appleTree: AppleTree) { 
     val apple = appleTree.pick().also { apple -> 
      this.weight += apple.weight 
      add(apple) 
     } 
     ... 
    } 
    ... 
    fun add(fruit: Fruit) = ... 
} 

使用apply這裏將陰影this,使this.weight要提到蘋果,的水果籃。


注:我無恥地接過例子from my blog

15

有喜歡here幾個文章,here,值得去看一看。

我認爲這是當你需要更短,更簡潔的幾行內容,並避免分支或條件語句檢查(例如,如果不是空的,然後這樣做)。

我喜歡這個簡單的圖表,所以我把它鏈接到這裏。你可以從Sebastiano Gottardo寫的this中看到它。

enter image description here

也請看看下面伴隨我的解釋圖表。

概念

我認爲這是一種角色扮演的代碼塊中的方式,當你調用這些函數+您是否希望自己回(到鏈通話功能,或設置爲結果變量等)。

以上是我的想法。

概念實例

讓我們來看看例子對所有的人都在這裏

1)myComputer.apply { }意味着你要作爲一個主要演員(你要認爲你的電腦),並且希望自己回到(電腦),所以你可以做

var crashedComputer = myComputer.apply { 
    // you're the computer, you yourself install the apps 
    // note: installFancyApps is one of methods of computer 
    installFancyApps() 
}.crash() 

是啊,你自己剛剛安裝的應用程序,崩潰自己,並保存自己作爲參考,讓別人看,並用它做什麼。

2)myComputer.also {}意味着你完全確定你不是電腦,你是想用它做什麼外人,也希望它的計算機作爲一個返回的結果。

var crashedComputer = myComputer.also { 
    // now your grandpa does something with it 
    myGrandpa.installVirusOn(it) 
}.crash() 

3)with(myComputer) { }意味着你是主要演員(計算機),你希望自己作爲一個結果返回。

with(myComputer) { 
    // you're the computer, you yourself install the apps 
    installFancyApps() 
} 

4)myComputer.run { }意味着你是主要演員(計算機),你希望自己作爲一個結果返回。

myComputer.run { 
    // you're the computer, you yourself install the apps 
    installFancyApps() 
} 

,但它在一個很微妙的感覺,你可以調用鏈就像run { }以下

myComputer.run { 
    installFancyApps() 
}.run { 
    // computer object isn't passed through here. So you cannot call installFancyApps() here again. 
    println("woop!") 
} 

這是由於run {}是從with { }不同的是擴展功能,但with { }不是。所以你調用run { }this裏面的代碼塊會反映到調用者類型的對象中。你可以看到this對於run {}with {}之間的區別有一個很好的解釋。

5.)myComputer.let { }意味着你是局外人,看着計算機,並且想要做一些關於它的事情,而不用擔心計算機實例再次返回給你。

myComputer.let { 
    myGrandpa.installVirusOn(it) 
} 

的方式來看待它

我往往看alsolet的東西這是外部的,外部的。每當你說出這兩個字時,就像你試圖在某件事上採取行動一樣。let在這臺電腦上安裝病毒,並also崩潰。因此,這可以確定你是否是演員。

對於結果部分,顯然存在。 also表示這也是另一回事,所以你仍然保留對象本身的可用性。因此它返回它作爲結果。

其他一切與this聯繫。另外run/with顯然不利於回報對象自己回來。現在你可以區分所有這些。

我認爲有時候,當我們離開100%編程/基於邏輯的例子時,我們處於更好的概念化的位置。但這取決於對:)