Что означает "с" в Котлине?
Я читал документы на нем 3 раза, и я до сих пор не знаю, что он делает. Может ли кто-нибудь ELI5 (Объяснить, как мне пять), пожалуйста? Вот как я его использую:
fun main(args: Array<String>) {
val UserModel = UserModel()
val app = Javalin.create().port(7000).start()
with (app) {
get("/users") {
context -> context.json(UserModel)
}
}
}
Ответы
Ответ 1
В документации говорится:
inline fun <T, R> with(receiver: T, block: T.() -> R): R (source)
Вызывает указанный функциональный блок с данным приемником в качестве приемника и возвращает его результат.
Я думаю, что он вызывает функцию (block
), где this
в области block
есть receiver
.
Независимо от возвращаемого block
является возвращаемым типом.
По существу вызов метода, в котором вы предоставляете неявный this
, и может возвращать любой результат из него.
Вот пример, демонстрирующий:
val rec = "hello"
val returnedValue: Int = with(rec) {
println("$this is ${length}")
lastIndexOf("l")
}
rec
в этом случае является получателем вызова функции - this
в области block
. $length
и lastIndexOf
вызываются в приемнике.
Возвращаемое значение можно увидеть как Int
, потому что это последний вызов метода в body
- это параметр типового типа R
подписи.
Ответ 2
Определение with
:
inline fun <T, R> with(receiver: T, block: T.() -> R): R (source)
Фактически реализация выполняется прямо: block
выполняется в receiver
, который работает для любого типа:
receiver.block() //that the body of `with`
Замечательно отметить здесь тип параметра T.() -> R
:
Он называл функциональный литерал с приемником. Это фактически лямбда, которая может получить доступ к членам приемника без каких-либо дополнительных квалификаторов.
В вашем примере доступ к context
приемника with
app
осуществляется таким образом.
Помимо функций stdlib, таких как with
или apply
, эта функциональность делает Kotlin отличным для записи Domain Specific Languages , поскольку позволяет создавать области, в которых у вас есть доступ к определенным функциям.
Ответ 3
with
используется для доступа к объектам и методам без обращения к объекту один раз за доступ. Это (в основном) для сокращения вашего кода. Он часто используется при построении объекта:
// Verbose way, 219 characters:
var thing = Thingummy()
thing.component1 = something()
thing.component2 = somethingElse()
thing.component3 = constantValue
thing.component4 = foo()
thing.component5 = bar()
parent.children.add(thing)
thing.refcount = 1
// Terse way, 205 characters:
var thing = with(Thingummy()) {
component1 = something()
component2 = somethingElse()
component3 = constantValue
component4 = foo()
component5 = bar()
parent.children.add(this)
refcount = 1
}