Funkcje zakresu ("funkcje zakresowe") w Kotlinie to standardowe funkcje (let, also, run, apply, with), które pozwalają zarządzać kontekstem wykonania bloku kodu dla obiektu. Różnią się:
it lub przez this.| Funkcja | this/it | Zwraca | Do czego? |
|---|---|---|---|
| let | it | rezultat | łańcuch operacji, praca z nullable, mapowanie |
| also | it | obiekt | efekty uboczne, logowanie, debugowanie |
| run | this | rezultat | obliczenia, inicjalizacja z wartością zwracaną |
| apply | this | obiekt | konfiguracja obiektu, budowniczowie |
| with | this | rezultat | praca z zewnętrznymi API, obiekt „na zewnątrz” |
Przykłady:
let: wygodne, gdy obiekt jest nullable:val str: String? = "Text" str?.let { println(it.length) }
apply: konfiguracja obiektu:val paint = Paint().apply { color = Color.RED strokeWidth = 2f }
run: wykonanie na obiekcie, zwraca wynik:val length = "abcde".run { length }
with: do pracy z zewnętrznym obiektem:val sb = StringBuilder() with(sb) { append("Hello, ") append("world!") toString() }
also: do efektów ubocznych (np. logi):val list = mutableListOf(1, 2, 3) list.also { println("Before: $it") }.add(4)
it, zmienianie właściwości obiektu nie jest zbyt wygodne.this / it), co jest przydatne dla budowniczych.with to zwykła funkcja, nie extension.Jaka jest różnica między let a also?
Odpowiedź:
it wewnątrz bloku,let zwraca wynik lambdy, często używane do łańcuchów transformacji,also zwraca oryginalny obiekt, używane do efektów ubocznych (log, debug), aby nie zakłócać łańcucha przekształceń.Przykład:
val result = listOf(1).also { println(it) }.map { it * 2 } // wynik — List<Int>
Historia
Nowicjusz użył let do konfiguracji obiektu, sądząc, że można w ten sposób zmienić jego stan „w łańcuchu”. W rezultacie po zakończeniu bloku konfiguracji otrzymał nie obiekt, lecz wynik lambdy (na przykład nic), co zakłóciło łańcuch budowania DSL.
Historia
Podczas pisania kodu do pracy z obiektami nullable, użyto run zamiast let, nie zauważając różnicy w zwracanej wartości. W rezultacie wynik wyrażenia różnił się od oczekiwanego, pojawiały się null, gdzie nie powinno ich być — logika aplikacji została złamana.
Historia
W dużym budowniczym przypadkowo użyto with dla obiektów wewnętrznych, licząc na wzorzec extension. Ponieważ with nie jest funkcją extension, łańcuch kilku bloków with działał nieprawidłowo, wewnętrzne wywołania się myliły i przekraczały zakres aktualnego obiektu. Konieczne było całkowite przepisanie hierarchii tworzenia obiektów.