Scope functions у Котлину су пет функција стандардне библиотеке (let, run, with, apply, also) које извршавају блок кода у контексту објекта. Оне се разликују по начину приступа објекту (путем it или this) и повратној вредности (контекстни објекат или резултат ламбде). Према документацији Котлина (2026), правилан избор scope function смањује boilerplate код за 25–40%. Scope functions помажу у писању иницијализације, конфигурације и трансформације објеката у декларативном стилу.
Главно
Scope functions (функције опсега) — скуп од пет функција (let, run, with, apply, also) уграђених у стандардну библиотеку Котлина. Свака од њих прима ламбду и привремено мења опсег видљивости тако да се унутар ламбде код извршава у контексту одређеног објекта. Ово елиминише понављање имена објекта при вишеструким позивима и групише повезане операције у један блок.
Две кључне карактеристике разликују scope functions: начин приступа контекстном објекту (путем this или it) и повратна вредност (сам контекстни објекат или резултат ламбде). Приступ путем this чини објекат имплицитним примаоцем — методе и својства се позивају без префикса. Приступ путем it преноси објекат као експлицитни параметар ламбде. Повратак објекта омогућава градњу ланаца, повратак резултата — доделу трансформисане вредности.
Историјски, scope functions су се појавиле као замена за класични образац Builder и привремене променљиве за иницијализацију. Уместо креирања засебне builder класе, програмер пише apply { својство1 = ...; својство2 = ... }. Ово смањује количину кода и чини иницијализацију читљивијом. У екосистему Котлина, scope functions се користе у свим оквирима и библиотекама као стандардни идиом језика.
Избор одговарајуће scope function одређују два питања: да ли желите да користите this или it за приступ објекту, и да ли желите да вратите сам објекат или резултат ламбде. Комбинација две бинарне карактеристике даје четири могуће варијанте, а with заузима посебно место као једина функција која није проширење.
| Функција | Приступ | Повратак | Проширење? | Типичан сценарио |
|---|---|---|---|---|
| let | it | резултат ламбде | да | Трансформација, null провера |
| run | this | резултат ламбде | да | Израчунавање са контекстом |
| with | this | резултат ламбде | не | Груписање позива |
| apply | this | контекстни објекат | да | Иницијализација својстава |
| also | it | контекстни објекат | да | Споредни ефекти, логирање |
За конфигурацију објекта без враћања нове вредности користите apply (приступ путем this) или also (приступ путем it). За израчунавање нове вредности на основу објекта користите let (приступ путем it) или run (приступ путем this). За груписање позива без ланчања користите with. Праћење ове шеме чини код предвидљивим за друге програмере упознате са Котлином.
apply — scope function која враћа контекстни објекат и омогућава приступ њему путем this. То је идеалан алат за иницијализацију својстава објекта након креирања. Унутар apply блока могуће је постављати својства без понављања имена објекта. Метода враћа сам објекат, што омогућава уграђивање apply у ланце или коришћење у иницијализаторима.
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
}
У листингу, apply конфигурише ServerConfig, приступајући својствима директно путем this (this изостављен). Без apply морало би се писати config.host = ..., config.port = ... — три понављајуће референце на исту променљиву. Повратак објекта омогућава чување резултата конфигурације у val config. also, за разлику од apply, преноси објекат путем it и погодан је за споредне ефекте.
fun saveUser(user: User) {
validate(user).also { result ->
println("Резултат валидације: $result")
}
val savedUser = user.also {
log("Saving user ${it.id}")
database.save(it)
}
}
У примеру, also се користи за логирање — враћајући оригинални објекат, извршава споредни ефекат (испис поруке) без измене објекта. Ово је ланац: validate(user) враћа User, also логира резултат и прослеђује корисника даље. also је такође користан за додавање елемената у колекције или отклањање грешака усред ланца трансформација.
let — scope function која враћа резултат ламбде и преноси контекст путем it. То је основна функција за null-безбедне трансформације: ако је објекат nullable, комбинација ?.let { } ће извршити блок само при ненултој вредности. let се такође користи за ограничавање опсега видљивости привремених променљивих и map-сличне трансформације из једног типа у други.
fun findUser(id: Int): User?
val displayName = findUser(42)?.let { user ->
"${user.name} (${user.email})"
} ?: "Unknown user"
// let са трансформацијом колекције
val numbers = listOf("1", "2", "3")
val parsed = numbers.firstOrNull()?.let {
it.toIntOrNull()
} ?: 0
У првом примеру, let се позива путем ?. — блок се извршава само ако је findUser вратио ненулту вредност. Ламбда прима user путем it (може се преименовати ради јасноће) и враћа форматирани стринг. Ако корисник није пронађен — Елвис оператор ?: даје подразумевану вредност. У другом примеру, let претвара стринг у број са потенцијалним null.
run — аналог let-а са приступом путем this, који враћа резултат ламбде. run је погодан за израчунавања где је потребан контекст објекта, али се враћа нова вредност. Позив run() без објекта (као run { ... }) ствара привремени опсег видљивости за променљиве. with — непроширење са приступом путем this, погодно за груписање позива без ланчања.
// run као контекстуално израчунавање
val transformed = listOf(1, 2, 3).run {
filter { it > 1 }.map { it * 10 }
}
println(transformed) // [20, 30]
// with за груписање позива
val info = with(StringBuilder()) {
append("Name: ")
append("Alice")
toString()
}
У примеру, run на листи враћа резултат филтрирања и мапирања — саму трансформацију, а не листу. with прима StringBuilder као аргумент (не путем тачке) и унутра ради са this: append, append, toString. Резултат with — стринг info. Избор између run и with је често субјективан, али with је пожељнији када се објекат преноси из другог места без ланца позива.
with се разликује од осталих scope functions по томе што није функција-проширење. Она прима објекат као први аргумент, а ламбду као други. Унутар ламбде, објекат је доступан путем this. with је погодан за груписање позива метода објекта без чувања резултата или када је потребно привремено „ући” у контекст ради читања више својстава.
val user = User("Alice", "alice@example.com", "Admin")
val summary = with(user) {
"User $name has role $role and email $email"
}
println(summary)
// with за иницијализацију UI компоненте
with(TextView(context)) {
text = "Hello"
textSize = 18.0f
setTextColor(Color.BLUE)
}
У првом примеру, with формира стринг summary, приступајући својствима user директно путем this. Без with морало би се писати „User ${user.name} has role ${user.role}” — вишеструко понављање user. У другом примеру, with групише конфигурацију TextView: сви методи и својства се позивају на једном објекту без понављања. Недостатак with — немогућност употребе у ланцу, јер није проширење и не враћа контекстни објекат.
Често постављана питања
Користите apply — враћа објекат и омогућава приступ путем this, омогућавајући постављање својстава без понављања имена објекта. also је погодан ако је потребан експлицитни параметар it ради разликовања од својстава објекта.
let преноси контекст путем it (експлицитни параметар), run — путем this (имплицитни прималац). let је погодан за null провере и трансформације, run — за израчунавања са контекстом. Обе враћају резултат ламбде.
with није проширење — прима објекат као аргумент. Користите with за груписање позива када ланац није потребан. apply — проширење које враћа објекат, погодно у иницијализаторима и builder обрасцима.
Да, али будите опрезни са this — угнежђени this стварају забуну. Користите let или also са експлицитним именима за угнежђене контексте да бисте избегли двосмисленост при позивању спољашњег објекта.
Све scope functions су inline, па не стварају додатни overhead за анонимне класе. Разлика у перформансама између њих је занемарљива. Избор треба да се заснива на читљивости и конвенцијама, а не на брзини.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође