Kotlin Kapsam İşlevlerini Anlamanın Basit Yolu

Bir önceki paylaşımımdaki kapsam fonksiyon örneklerine bakarsanız buradatüm bu Kotlin Kapsam İşlevlerinin (örn. let
, run
, with
, apply
, also
) aynı şeyi başarabilir. Hepsi değiştirilebilir, sözdiziminde biraz farklı.
Sözdizimi Farklılıkları
Önce aralarındaki sözdizimi farklarını anlayalım.
Kaynak: kotlinlang.org
Not 1: Tüm bu kapsam işlevleri, aşağıdakiler dışında genişletme işlevleridir:
run
vewith
. Onlar 2kişirun
kapsam işlevleri. Biri uzantılı, diğeri uzantı işlevi olmayan.
val str = "test"
str.run {
println(this)
}
with(str) {
println(this)
}
run {
println(str)
}
Not 2: dönüş değeri lambda sonucu iade etmek anlamına gelir son satır döndürülen değer lambda ifadesinde. Tüm kapsam işlevlerinin dönüş değeri, aşağıdakiler dışında lambda sonucudur
apply
vealso
Hangi bağlam nesnesi Geri döndü.
val str = "test"
val tmp1 = str.run {
println(this)
}
println(tmp1)
val tmp2 = str.apply {
println(this)
}
println(tmp2)
Not 3: Kapsam içinde, nesneye şu şekilde başvurabiliriz:
this
veyait
.
run
,with
veapply
kullanmakthis
.let
vealso
kullanmakit
val str = "test"
str.run {
println(this)
}
str.let {
println(it)
}
Kafa karıştırıcı…
İtiraf etmeliyim ki tüm bu farklılıkları anlamaya çalışmak kafamı daha da karıştırıyor! Bunun nedeni, sözdiziminin kendisinin bunları tam olarak ne zaman ve nasıl kullanmamız gerektiğini açıklamamasıdır?
Önemli olan kısım sözdizimi değil, kullanımları ancak geliştirici genellikle bunları nasıl ve ne zaman kullanır? Aşağıda bunların daha pratik kullanımlarına bakalım!
Diyelim ki aşağıdaki sınıfa sahibiz.
class Dog(val name: String) {
var age: Int = 0
var owner: String? = null
fun bark() = println("$name is barking")
fun eat() = println("$name is eating")
}
Ne Zaman Kullanılır let
?
let
genellikle kaçınmak için null yapılabilir nesne için kullanılır NullPointerException
Boş kontrolü değiştir
var nullableDog: Dog? = null
if (nullableDog != null) {
nullableDog.age++
nullableDog.owner = "Vincent"
nullableDog.bark()
nullableDog.eat()
}
val age = nullableDog?.age
ile birlikte let
var nullableDog: Dog? = null
val age = nullableDog?.let {
it.owner = "Vincent"
it.bark()
it.eat()
it.age++
}
it
okunabilirlik için herhangi bir adla değiştirilebilir. Bu, özellikle sahipseniz kullanışlıdır. zincirleme / iç içe kapsam işlevleri, ad, iç ve dış kapsam arasında ayrım yapmak için kullanılabilir.
val age = nullableDog?.let { myDog ->
myDog.owner = "Vincent"
myDog.bark()
myDog.eat()
myDog.age++
}
Not: Yukarıdaki bu örnek, iç içe geçmiş bir kapsam işlevi DEĞİLDİR. Şahsen ondan nefret ediyorum ve bundan kaçınacağım
Bu okunabilirliğe ihtiyacınız yoksa, let
oldukça işe yaramaz bence tamamen değiştirilebilir çünkü run
ve belirtmeniz gerekmez it
bağlam nesnesine başvurmak için.
Ne Zaman Kullanılır run
?
run
kullanım şuna benzer let
bu, boş denetimi gerçekleştirmek için kodunuzu okunabilir hale getirir. Dan beri this
lambda ifadesinde atlanabilir, kodun daha temiz olduğunu hissediyorum. Bu nedenle, kişisel olarak tercih ederim run
üzerinde let
.
var nullableDog: Dog? = null
val age = nullableDog?.run {
owner = "Vincent"
bark()
eat()
age++
}
Ne Zaman Kullanılır run
Uzatma Dışı İşlev?
run
uzantısı olmayan işlev, diğer dillerdeki standart kapsam işlevine çok benzer. dog
iç kapsamdaki değişken ifade eder Jimmy
ve dog
dış kapsamdaki değişken ifade eder Lily
val dog = Dog("Lily")
run {
val dog = Dog("Jimmy")
println("Dog name is ${dog.name}")
}
println("Dog age is ${dog.name}")
Not: Bu muhtemelen nadiren kullanılır. Bunu kullanan herhangi bir kod görmedim. Farklı bir işleve ayırmak, muhtemelen kullanmaktan daha iyi bir fikirdir.
run
uzantı olmayan işlev, kapsam işlevi.
Ne Zaman Kullanılır with
?
with
benzer run
boş olmayan bir nesne üzerinde çalışmak istediğinizde kullanılması dışında. Nesneniz boşsa, KULLANMAYIN with
.
val dog = Dog("Lily")
val age = with(dog) {
owner = "Vincent"
bark()
eat()
age++
}
Ne Zaman Kullanılır apply
?
apply
genellikle nesne oluşturma sırasında sınıftaki özellikleri başlatmak için kullanılır.
sen bunu değiştir
val dog = Dog("Lily")
dog.owner = "Vincent"
dog.age = 10
ile birlikte
val dog = Dog("Lily").apply {
owner = "Vincent"
age = 10
}
Ne Zaman Kullanılır also
?
also
hemen hemen aynıdır apply
ve nadiren buna ihtiyacımız var. Benzer let
muhtemelen değiştirebileceğiniz iç içe kapsam işlevlerinde okunabilirlik sorunu için gereklidir. it
daha anlamlı bir isimle.
val dog = Dog("Lily").also {
it.owner = "Vincent"
it.age = 10
}
Özet
Bu kapsam işlevlerini şu şekilde kullanacağım:
- İzin Vermek – yuvalanmış/zincirleme kapsam işlevlerinde okunabilirlik sorunu olmadıkça bunu boş denetim için KULLANMAYIN
- koşmak – bunun yerine boş kontrol için bunu kullanın. Ancak, kullanmanız gerekiyorsa
this
nesne referansı için kullanmayı düşününlet
okunabilirlik yerine - çalıştır (uzantı olmayan işlev) – muhtemelen gerekli DEĞİLDİR, daha iyi okunabilirlik için bu kapsamı bir işlev çağrısı ile değiştirin
- ile birlikte – bunu null yapılamayan nesne için kullanın
- uygulamak – bunu nesne oluşturma ve başlatma için kullanın
- ayrıca – iç içe kapsam işlevinde okunabilirlik sorunu olmadıkça bunu KULLANMAYIN. Kullanmak
apply
yerine.
Kapsam işlevinin amacı, kodu azaltın ve kodunuzu okunabilir hale getirin. Yani, bunu başarmak için onları nasıl kullanmak istediğiniz gerçekten size kalmış. Bazen bu sadece kişisel bir şey olabilir.
Örneğin, burada önerdiklerim (yani KULLANMAYIN) let
boş kontrol için) muhtemelen çoğunluğa aykırıdır, ancak buluyorum run
daha düzdür. Seçeneklerimi basitleştiriyor. sadece arasında seçim yapmam gerekiyor run
ve with
- kullanmak
run
null yapılabilir değişken için - kullanmak
with
null olmayan değişken için.
Bu basit değil mi?
Kapsam işlevi, sahip olunması güzel bir özelliktir. Bunları kullanmasanız bile, kodunuz hala okunabilir olduğu sürece sorun değil.