2017-08-31 9 views

Odpowiedz

26

Wszystkie te funkcje służą do przełączania zakresu bieżącej funkcji/zmiennej. Są one używane do przechowywania rzeczy, które należą do siebie w jednym miejscu (głównie inicjalizacje).

Oto kilka przykładów:

run - zwraca cokolwiek chcesz i ponownie zakresów zmienną jest używany do this

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

     generate() 
    } 

Generator hasło jest teraz rescoped jak this i dlatego możemy ustawić seed, hash i hashRepetitions bez użycia zmiennej. generate() zwróci instancję z Password.

apply jest podobna, ale powróci this:

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

To szczególnie przydatne jako zamiennik dla wzoru Builder, a jeśli chcesz, aby ponownie wykorzystać pewne konfiguracje.

let - używany głównie w celu uniknięcia kontroli zerowych, ale może być również używany jako zamiennik dla run. Różnica polega na tym, że this wciąż będzie taka sama, jak przed i uzyskać dostęp do ponownego scoped zmienną korzystając it:

val fruitBasket = ... 

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

Powyższy kod doda jabłko do kosza tylko jeśli nie jest zerowa. Również zauważyć, że it jest teraz nie opcjonalne już więc nie napotkasz NullPointerException tutaj (aka nie trzeba używać ?. dostęp do jego atrybutów.)

also - używaj go, gdy chcesz użyć apply, ale nie chcesz, aby cień 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) = ... 
} 

Korzystanie apply tutaj by cień this, tak że this.weight by zapoznać się z jabłkiem i nie do kosza owoców.


Uwaga: I bezczelnie wziął przykłady from my blog

15

Istnieje kilka więcej artykułów takich jak here i here że warto spojrzeć.

Myślę, że to zależy od tego, kiedy potrzebujesz krótszej, bardziej zwięzłej w kilku linijkach i unikania rozgałęzień lub warunkowego sprawdzania oświadczeń (np. Jeśli nie jest pusta, to zrób to).

Uwielbiam ten prosty wykres, więc połączyłem go tutaj. Można go zobaczyć z this, jak napisał Sebastiano Gottardo.

enter image description here

Proszę również spojrzeć na wykres towarzyszącej moje wyjaśnienie poniżej.

Concept

myślę go jako rolę gra drogę wewnątrz bloku kodu po wywołaniu tych funkcji + czy chcesz się z powrotem (do funkcji połączeń łańcucha, lub ustawić spowodować zmienna, etc).

Powyżej jest to, co myślę.

Concept Przykład

Zobaczmy przykłady dla nich wszystkich tutaj

1.) myComputer.apply { } oznacza, że ​​chcesz działać jako głównego aktora (chcesz, aby myśleć, że jesteś komputer), a chcesz się z powrotem (komputer), dzięki czemu można zrobić

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

tak, ty sam wystarczy zainstalować aplikacje, crash siebie i zapisane siebie jako punkt odniesienia, by inni mogli zobaczyć i coś z tym zrobić.

2.) myComputer.also {} oznacza, że ​​jesteś całkowicie pewien, że nie sąkomputer, jesteś outsiderem, który chce coś z tym zrobić, a także chce, komputer jako zwróconego wyniku.

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

3.) with(myComputer) { } oznacza, że ​​jesteś głównym aktorem (komputer), a ty nie chcą się wskutek powrotem.

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

4.) myComputer.run { } oznacza, że ​​jesteś głównym aktorem (komputer), a ty nie chcą się wskutek powrotem.

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

ale różni się od with { } w bardzo subtelnym poczuciem, że można zadzwonić łańcuch run { } jak na poniższym

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

Wynika to run {} jest funkcja rozszerzenie, ale with { } nie jest. Więc zadzwonisz pod numer run { } i this wewnątrz bloku kodu zostanie odzwierciedlony typ obiektu wywołującego. Możesz zobaczyć this doskonałe wyjaśnienie różnicy między run {} i with {}.

5.) oznacza, że ​​jesteś osobą postronną, która patrzy na komputer i chce coś z tym zrobić, nie zwracając uwagi na to, aby instancja komputera została zwrócona do Ciebie ponownie.

myComputer.let { 
    myGrandpa.installVirusOn(it) 
} 

Droga na to patrzeć

staram się patrzeć na also i let jako coś, co jest zewnętrzne, na zewnątrz. Ilekroć wypowiadasz te dwa słowa, to tak, jakbyś próbował coś zrobić.let zainstaluj wirusa na tym komputerze, a also uruchom go. Więc to zależy od tego, czy jesteś aktorem czy nie.

Dla części wynikowej wyraźnie tam jest. also wyraża, że ​​jest to kolejna rzecz, więc nadal zachowujesz dostępność samego obiektu. W związku z tym zwraca go jako wynik.

Wszystko inne kojarzy się z this. Dodatkowo, run/with wyraźnie nie jest zainteresowany powrotem z powrotem do obiektu. Teraz możesz je wszystkie rozróżnić.

Myślę, że czasami, gdy odchodzimy od 100% programowania/logiki na podstawie przykładów, to jesteśmy w lepszej pozycji do konceptualizacji rzeczy. Ale to zależy dobrze :)

Powiązane problemy