Can you delegate a property to another property in Kotlin? I have the following code:
class SettingsPage {
lateinit var tagCharacters: JTextField
lateinit var tagForegroundColorChooser: ColorPanel
lateinit var tagBackgroundColorChooser: ColorPanel
var allowedChars: String
get() = tagCharacters.text
set(value) = tagCharacters.setText(value)
var tagForegroundColor by tagForegroundColorChooser
var tagBackgroundColor by tagBackgroundColorChooser
}
In order to get property delegation, I declare the following two extension functions:
operator fun ColorPanel.getValue(a: SettingsPage, p: KProperty<*>) = selectedColor
operator fun ColorPanel.setValue(a: SettingsPage, p: KProperty<*>, c: Color?) { selectedColor = c }
However, what I would like to write is something like the following:
class SettingsPage {
lateinit var tagCharacters: JTextField
lateinit var tagForegroundColorChooser: ColorPanel
lateinit var tagBackgroundColorChooser: ColorPanel
var allowedChars: String by Alias(tagCharacters.text)
var tagForegroundColor by Alias(tagForegroundColorChooser.selectedColor)
var tagBackgroundColor by Alias(tagBackgroundColorChooser.selectedColor)
}
Is this possible to do Kotlin? How do I write the class Alias
?
A “Delegate” is just a class that provides the value of a property and handles its changes. This will help us to delegate(assign or pass on), the getter-setter logic altogether to a different class so that it can help us in reusing the code. This is an alternative to inheritance property.
Delegation (in computer science) is the assignment of authority from one instance to another. It can operate mutable as well as static relationship between classes, and inheritance, in turn, is based on the constant concept.
A delegate is just a class that provides the value for a property and handles its changes. This allows us to move, or delegate, the getter-setter logic from the property itself to a separate class, letting us reuse this logic.
Android Dependency Injection using Dagger with Kotlin Kotlin supports “delegation” design pattern by introducing a new keyword “by”. Using this keyword or delegation methodology, Kotlin allows the derived class to access all the implemented public methods of an interface through a specific object.
UPD: Since Kotlin 1.4, the standard library includes the necessary extensions that allow this out of the box:
class MyClass(var memberInt: Int, val anotherClassInstance: ClassWithDelegate) {
var delegatedToMember: Int by this::memberInt
var delegatedToTopLevel: Int by ::topLevelInt
val delegatedToAnotherClass: Int by anotherClassInstance::anotherClassInt
}
var MyClass.extDelegated: Int by ::topLevelInt
Yes, it's possible: you can use a bound callable reference for a property that you store in the alias, and then the Alias
implementation will look like this:
class Alias<T>(val delegate: KMutableProperty0<T>) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): T =
delegate.get()
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
delegate.set(value)
}
}
And the usage:
class Container(var x: Int)
class Foo {
var container = Container(1)
var x by Alias(container::x)
}
To reference a property of the same instance, use this::someProperty
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With