Delegated properties

We've already seen previously in Chapter 3, Classes and Object-Oriented Programming, about classes how Kotlin's by keyword can be used for class delegation. The same keyword can also be used for property delegation. As the name suggests, this concept allows a property's get or set methods to be delegated to another object. First, we’ll learn how to write a delegate, then we’ll see what delegates are included with the standard library.

Let's say we want a property that is lazily initialized, that is, initialized when accessed for the first time. We can use a delegate property for this:

private val str by lazyProperty { "I'm lazily initialized" }

The syntax for a delegate property is the by keyword, followed by an expression that returns an instance of the ReadOnlyProperty interface in the case of an immutable property, or the ReadWriteProperty interface in the case of a mutable property. This is how the interfaces are defined:

public interface ReadOnlyProperty<in R, out T> {
public operator fun getValue(thisRef: R, property: KProperty<*>): T
}

The ReadWriteProperty interface also has a setter method:

public interface ReadWriteProperty<in R, T> {
public operator fun getValue(thisRef: R, property: KProperty<*>): T
public operator fun setValue(thisRef: R, property: KProperty<*>, value: T)
}

Now, let's create a class that implements ReadOnlyProperty, which enables lazy initialization. Please note that this version is not thread safe. The standard library already ships with a thread safe delegate for lazy initialization, as we shall see later:

class LazyProperty<T>(private val valueFactory: () -> T) : ReadOnlyProperty<Any, T> {
private var instance: T? = null

override fun getValue(thisRef: Any, property: KProperty<*>): T {
if (instance == null) {
instance = valueFactory()
}
return instance!!
}
}

The interfaces have two generic parameters: the first one represents the type that will own the property, and the second the type of the property itself. In our case, we set the first generic argument to Any, which means that there are no restrictions on types that can host our delegated property. The second parameter is left as generic, which means that there are no restrictions on the property type itself and that the actual type will be determined at compile time.

getValue is a method that enables the delegated property; it states how the delegate provides the property value.

Delegates of mutable properties have to implement the ReadWriteProperty interface, and there you have one additional method, setValue, which states how the properties value is written.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.109.75