Kotlin da scope functions — bu standart kutubxonaning beshta funksiyasi (let, run, with, apply, also) bo'lib, ular ob'ekt kontekstida kod blokini bajaradi. Ular ob'ektga kirish usuli (it yoki this orqali) va qaytariladigan qiymat (kontekst ob'ekti yoki lambda natijasi) bilan farqlanadi. Kotlin hujjatlariga (2026) ko'ra, to'g'ri scope function tanlash shablon kodini 25–40% ga kamaytiradi. Scope functions ob'ektlarni ishga tushirish, sozlash va o'zgartirishni deklarativ uslubda yozishga yordam beradi.
Asosiy fikrlar
Scope functions (ko'rinish doirasi funksiyalari) — Kotlin standart kutubxonasiga o'rnatilgan beshta funksiyadan (let, run, with, apply, also) iborat to'plam. Ularning har biri lambda qabul qiladi va vaqtincha ko'rinish doirasini shunday o'zgartiradiki, lambda ichidagi kod ma'lum bir ob'ekt kontekstida bajariladi. Bu ko'p chaqiruvlarda ob'ekt nomini takrorlashdan qutqaradi va bog'liq operatsiyalarni bir blokda guruhlaydi.
Scope functions ni farqlovchi ikkita asosiy xususiyat: kontekst ob'ektiga kirish usuli (this yoki it orqali) va qaytariladigan qiymat (kontekst ob'ektining o'zi yoki lambda natijasi). This orqali kirish ob'ektni yashirin qabul qiluvchiga aylantiradi — metodlar va xususiyatlar prefikssiz chaqiriladi. It orqali kirish ob'ektni lambdaning aniq parametri sifatida uzatadi. Ob'ektni qaytarish zanjirlar qurishga, natijani qaytarish esa o'zgartirilgan qiymatni o'zlashtirishga imkon beradi.
Tarixiy jihatdan, scope functions klassik Builder namunasi va ishga tushirish uchun vaqtinchalik o'zgaruvchilarning o'rnini bosuvchi sifatida paydo bo'lgan. Alohida builder klassi yaratish o'rniga, dasturchi apply { xususiyat1 = ...; xususiyat2 = ... } yozadi. Bu kod hajmini kamaytiradi va ishga tushirishni yanada o'qiladigan qiladi. Kotlin ekotizimida scope functions barcha freymvorklar va kutubxonalarda tilning standart idiomasi sifatida ishlatiladi.
To'g'ri scope function tanlash ikkita savol bilan aniqlanadi: ob'ektga kirish uchun this yoki it dan foydalanmoqchimisiz va ob'ektning o'zini yoki lambda natijasini qaytarmoqchimisiz. Ikkita ikkilik xususiyatning kombinatsiyasi to'rtta mumkin variantni beradi, with esa kengaytma bo'lmagan yagona funksiya sifatida alohida o'rin tutadi.
| Funksiya | Kirish | Qaytarish | Kengaytma? | Oddiy stsenariy |
|---|---|---|---|---|
| let | it | lambda natijasi | ha | O'zgartirish, null tekshiruvi |
| run | this | lambda natijasi | ha | Kontekst bilan hisoblash |
| with | this | lambda natijasi | yo'q | Chaqiruvlarni guruhlash |
| apply | this | kontekst ob'ekti | ha | Xususiyatlarni ishga tushirish |
| also | it | kontekst ob'ekti | ha | Yon ta'sirlar, loglash |
Yangi qiymat qaytarmasdan ob'ektni sozlash uchun apply (this orqali kirish) yoki also (it orqali kirish) dan foydalaning. Ob'ekt asosida yangi qiymat hisoblash uchun let (it orqali kirish) yoki run (this orqali kirish) dan foydalaning. Zanjirsiz chaqiruvlarni guruhlash uchun with dan foydalaning. Ushbu sxemaga rioya qilish kodni Kotlin biladigan boshqa dasturchilar uchun bashorat qilinadigan qiladi.
apply — kontekst ob'ektini qaytaradigan va unga this orqali kirishni ta'minlaydigan scope function. Bu ob'ekt yaratilgandan so'ng uning xususiyatlarini ishga tushirish uchun ideal vositadir. apply bloki ichida xususiyatlarni ob'ekt nomini takrorlamasdan o'rnatish mumkin. Metod ob'ektning o'zini qaytaradi, bu apply ni zanjirlarga kiritish yoki ishga tushiruvchilarda ishlatish imkonini beradi.
data class ServerConfig(
var host: String = "localhost",
var port: Int = 8080,
var useTls: Boolean = false
)
val config = ServerConfig().apply {
host = "api.example.com"
port = 443
useTls = true
}
Ro'yxatda apply ServerConfig ni sozlaydi, xususiyatlarga to'g'ridan-to'g'ri this orqali murojaat qiladi (this tushirib qoldirilgan). Apply bo'lmaganida config.host = ..., config.port = ... yozish kerak bo'lardi — bitta o'zgaruvchiga uchta takrorlanuvchi murojaat. Ob'ektni qaytarish sozlash natijasini val config da saqlash imkonini beradi. also, apply dan farqli o'laroq, ob'ektni it orqali uzatadi va yon ta'sirlar uchun mos keladi.
fun saveUser(user: User) {
validate(user).also { result ->
println("Tekshirish natijasi: $result")
}
val savedUser = user.also {
log("Saving user ${it.id}")
database.save(it)
}
}
Misolda also loglash uchun ishlatiladi — asl ob'ektni qaytarib, ob'ektni o'zgartirmasdan yon ta'sir (xabarni chop etish) bajaradi. Bu zanjir: validate(user) User ni qaytaradi, also natijani loglaydi va foydalanuvchini oldinga uzatadi. also shuningdek to'plamlarga elementlar qo'shish yoki o'zgartirishlar zanjiri o'rtasida nosozliklarni tuzatish uchun foydalidir.
let — lambda natijasini qaytaradigan va kontekstni it orqali uzatadigan scope function. Bu null-xavfsiz o'zgartirishlar uchun asosiy funksiya: agar ob'ekt nullable bo'lsa, ?.let { } kombinatsiyasi blokni faqat null bo'lmagan qiymatda bajaradi. let shuningdek vaqtinchalik o'zgaruvchilarning ko'rinish doirasini cheklash va bir turni boshqasiga map-ga o'xshash o'zgartirish uchun ishlatiladi.
fun findUser(id: Int): User?
val displayName = findUser(42)?.let { user ->
"${user.name} (${user.email})"
} ?: "Unknown user"
// let to'plam o'zgartirishi bilan
val numbers = listOf("1", "2", "3")
val parsed = numbers.firstOrNull()?.let {
it.toIntOrNull()
} ?: 0
Birinchi misolda let ?. orqali chaqiriladi — blok faqat findUser null bo'lmagan qiymat qaytarganda bajariladi. Lambda user ni it orqali qabul qiladi (aniqlik uchun nomlash mumkin) va formatlangan satrni qaytaradi. Agar foydalanuvchi topilmasa — Elvis operatori ?: standart qiymat beradi. Ikkinchi misolda let satrni potensial null bilan raqamga o'zgartiradi.
run — this orqali kirish bilan let ning analogi, lambda natijasini qaytaradi. run ob'ekt konteksti talab qilinadigan, ammo yangi qiymat qaytariladigan hisoblashlar uchun qulay. Ob'ektsiz run() chaqiruvi (run { ... }) o'zgaruvchilar uchun vaqtinchalik ko'rinish doirasini yaratadi. with — this orqali kirish bilan kengaytma bo'lmagan, zanjirsiz chaqiruvlarni guruhlash uchun mos funksiya.
// run kontekstli hisoblash sifatida
val transformed = listOf(1, 2, 3).run {
filter { it > 1 }.map { it * 10 }
}
println(transformed) // [20, 30]
// with chaqiruvlarni guruhlash uchun
val info = with(StringBuilder()) {
append("Name: ")
append("Alice")
toString()
}
Misolda ro'yxatda run filtrlash va map natijasini qaytaradi — o'zgarishning o'zini, ro'yxatni emas. with StringBuilder ni argument sifatida qabul qiladi (nuqta orqali emas) va ichida this bilan ishlaydi: append, append, toString. with natijasi — info satri. run va with o'rtasidagi tanlov ko'pincha subyektivdir, ammo with ob'ekt boshqa joydan zanjirsiz uzatilganda afzalroqdir.
with boshqa scope functions dan shu bilan farqlanadiki, u kengaytma funksiyasi emas. U ob'ektni birinchi argument, lambdani esa ikkinchi argument sifatida qabul qiladi. Lambda ichida ob'ekt this orqali mavjud. with natijani saqlamasdan ob'ekt metodlarini guruhlash yoki bir nechta xususiyatlarni o'qish uchun vaqtinchalik kontekstga “kirish” kerak bo'lganda qulaydir.
val user = User("Alice", "alice@example.com", "Admin")
val summary = with(user) {
"User $name has role $role and email $email"
}
println(summary)
// with UI komponentini ishga tushirish uchun
with(TextView(context)) {
text = "Hello"
textSize = 18.0f
setTextColor(Color.BLUE)
}
Birinchi misolda with summary satrini shakllantiradi, user xususiyatlariga to'g'ridan-to'g'ri this orqali murojaat qiladi. With bo'lmaganida “User ${user.name} has role ${user.role}” yozish kerak bo'lardi — user ning ko'p marta takrorlanishi. Ikkinchi misolda with TextView sozlamalarini guruhlaydi: barcha metodlar va xususiyatlar takrorlanmasdan bitta ob'ektda chaqiriladi. With ning kamchiligi — zanjirda ishlatib bo'lmasligi, chunki u kengaytma emas va kontekst ob'ektini qaytarmaydi.
Tez-tez so'raladigan savollar
apply dan foydalaning — u ob'ektni qaytaradi va this orqali kirishni ta'minlaydi, xususiyatlarni ob'ekt nomini takrorlamasdan o'rnatish imkonini beradi. also ob'ektning xususiyatlaridan farqlash uchun aniq it parametri kerak bo'lganda mos keladi.
let kontekstni it orqali (aniq parametr), run — this orqali (yashirin qabul qiluvchi) uzatadi. let null tekshiruvlari va o'zgartirishlar uchun, run — kontekst bilan hisoblashlar uchun qulay. Ikkalasi lambda natijasini qaytaradi.
with kengaytma emas — ob'ektni argument sifatida qabul qiladi. Zanjir kerak bo'lmaganda chaqiruvlarni guruhlash uchun with dan foydalaning. apply — ob'ektni qaytaradigan kengaytma, ishga tushiruvchilar va builder namunalarida qulay.
Ha, lekin this bilan ehtiyot bo'ling — ichma-ich this lar chalkashlikka olib keladi. Ichma-ich kontekstlar uchun aniq nomlar bilan let yoki also dan foydalaning, tashqi ob'ektga murojaat qilishda noaniqlikni oldini olish uchun.
Barcha scope functions inline, shuning uchun ular anonim sinflar uchun qo'shimcha yuk yaratmaydi. Ularning o'rtasida samaradorlik farqi ahamiyatsiz. Tanlov tezlikka emas, balki o'qiladiganlik va konvensiyalarga asoslanishi kerak.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.