Custom Accessors
Sometimes, you will see a get()
or perhaps a set()
associated with a property. Those are custom accessors, replacing the stock ones that Kotlin would generate for you.
Defining Custom Accessors
Each Kotlin property is made up of a field, a getter function, and a setter function. By default, the getter and setter are code-generated for you, but you can override those with custom implementations if desired.
For example, here is a property with a custom getter function:
val stuff = mapOf("something" to "This is the 'something' value")
val something: String?
get() = stuff["something"]
fun main() {
println(something)
}
The custom getter goes on the line after the property declaration. It is declared as a get()
function and needs to return an object matching the property’s data type. Otherwise, though, the actual function implementation is up to you. In this case, we declare that the something
value really comes from the stuff
Map
, rather than from the field that ordinarily would be the value of something
.
Not surprisingly, you can override the setter function too. That requires a var
property, as a val
property has no setter. The setter appears after the property, alongside the getter (if there is one). The setter is a set(value)
function, where value
is the value that is being set. So in this example, we turn around and put that value
into the stuff
using our something
key:
val stuff = mutableMapOf<String, String?>("something" to "This is the 'something' value")
var something: String?
get() = stuff["something"]
set(value) { stuff["something"] = value }
fun main() {
something = "This is different"
println(something)
}
Note that users of the property are not affected by these changes. You use the same syntax for working with the property as before.
Referencing the Field
If you declare a normal simple property, Kotlin will create the corresponding field into which the data gets stored. The generated getter returns the value of the field, while the setter replaces the value in the field.
If you declare custom accessors, by default Kotlin will not generate a corresponding field… unless you choose to reference it from the custom accessor functions via the field
name. Then, Kotlin creates that field and field
serves as a reference to it. If your accessors reference field
, though, your property needs an initializer, to supply the initial value for field
.
So, this is basically what the default Kotlin code generation would look like if you did it manually:
var something: String = "This is the 'something' value"
get() = field
set(value) { field = value }
fun main() {
something = "This is different"
println(something)
}
Inline Getters
For a val
property, if your custom getter clearly indicates the data type of the property, you can skip putting the data type on the property itself. Instead, put the custom getter function immediately after the property name:
val stuff = mapOf("something" to "This is the 'something' value")
val something get() = stuff["something"]
fun main() {
println(something)
}
Configuration Without Customization
Sometimes, you do not need to fully customize the accessor, but simply configure it slightly.
For example, you might have a var
property in a class, because you need to assign a new value to it after initialization. However, modifying that property should be limited to instances of the class itself, whereas reading that property might be available to all classes. In other words, you want a semi-public property: public getter and private setter.
That is just a matter of having a private set
declaration, without a function body:
class Whatever {
var something: String = "This is the 'something' value"
private set
// TODO
}
Instances of Whatever
can modify the something
property, while everything else is limited to reading that property.
Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.