Я хочу написать функцию расширения, которая модифицирует «это», например:
var a = false a.toggle() // now a contains false
или
var a = 1 a.increment() // now a contains 2
Возможно ли это в Котлине?
Я могу создать функцию расширения, которая возвращает измененное значение, но оставляет «это» неизмененным, но я хочу еще больше удобства! Похоже, Свифт может это сделать.
Ссылки на переменные еще не поддерживаются, но вы можете создавать функции расширения для использования со ссылками на свойства :
fun KMutableProperty0<Boolean>.not() = set(get().not()) fun KMutableProperty0<Int>.inc() = set(get().inc()) var a = false var b = 1 fun main(vararg args: String) { ::a.not() // now `a` contains `true` ::b.inc() // now `b` contains `2` }
Или, если вы предпочитаете функции расширения, возвращайте новое значение вместе с настройкой:
fun KMutableProperty0<Boolean>.not(): Boolean = get().not().apply(setter) fun KMutableProperty0<Int>.inc(): Int = get().inc().apply(setter)
Вы не можете этого сделать, потому что вам потребуется передать a
по ссылке. Это невозможно в Котлине. Все аргументы функции в Kotlin передаются по значению.
Однако вы можете моделировать поведение, используя следующую конструкцию. Однако это не очень удобно.
fun Boolean.toggle(getter: () -> Boolean, setter: (Boolean) -> Unit) { setter(!getter()) } var a = false println(a) // prints false a.toggle({a}, {a = it}) // Or a.toggle(a::get, a::set), but that isn't supported (yet?) println(a) // prints true
Как и любой другой параметр функции, this
ссылка на объект. С другой стороны, var a
является ссылкой на тот же объект. Таким образом, в основном у вас есть две ссылки, указывающие на один и тот же экземпляр:
var a = false val this = a // a.toggle()
Нет никакой манипуляции, которую вы можете сделать с одной из этих ссылок и изменить другую. Они представляют собой несвязанные переменные с одинаковым значением, не более того.
То, что вы можете сделать (теоретически), состоит в том, чтобы сделать объект изменчивым:
class MutableBoolean(val value: Boolean) val a = MutableBoolean(false) a.toggle() fun MutableBoolean.toggle() {value = !value}