Custom Class Field Getters and Setters
Key points
- Kotlin classes can have properties (what we call fields in Java)
- Properties can be defined as
val
orvar
val
fields are read-only,var
fields are read-write- Fields are accessed directly by their name, just like constructor parameters
- TODO: Properties are public by default, but can also be private
- You can write custom getter and setter (accessor and mutator) methods for your properties with a special syntax
- The getter/setter methods can use a “backing field” named
field
(TODO:field
is kind of a reserved word in Kotlin but not really)
A field without custom getters or setters
If you just want a simple property in a class that you can read and modify, declare the field as a var
:
class Person() {
var name = ""
}
// create an instance
>>> val p = Person()
// no initial value
>>> p.name
// set the value
>>> p.name = "Al"
// get (access) the value
>>> p.name
Al
That shows how to get and set values of a simple property.
Custom get/set methods
Conversely, if you want to create custom get/set methods, define custom get()
and set()
methods just below the property. For example, imagine that you want to make a log entry every time someone accesses or updates the name
of a Person
:
class Person {
var name: String = "<no name>"
get() {
println("OMG, someone accessed 'name'")
return field
}
set(s) {
println("OMG, someone updated 'name' to be '$s'")
field = s
}
}
The REPL shows how this works:
>>> val p = Person()
>>> p.name
OMG, someone accessed 'name'
<no name>
>>> p.name = "Al"
OMG, someone updated 'name' to be 'Al'
>>> p.name
OMG, someone accessed 'name'
Al
Key points:
- The getter/setter methods can use a “backing field” named
field
field
is a way of referencing the value you’re referencing, in this case thename
fieldfield
is made available to you, but you don’t have to use it- Per the official Kotlin documentation, “A backing field will be generated for a property if it uses the default implementation of at least one of the accessors, or if a custom accessor references it through the field identifier.”
More examples
Here are a few more examples of Kotlin’s getter/setter approach.
First, a one-line getter with a multiline setter, both using the special backing field:
class Foo {
var prop: String = "initial value"
get() = field //no real need for this, just showing syntax
set(s) {
// do whatever you want with `s` ...
// then:
field = s
}
}
Second, multiline getters and setters:
class Bar {
var name = ""
get() {
val s = if (field == "") "hello" else "hello, ${field}"
return s
}
set(s) {
// do whatever you want with `s`
field = s
}
}
This is how you can use your own “backing field” instead of field
:
class Baz {
private var _name = ""
var name = ""
fun get() = _name
fun set(s: String) {
_name = s
}
}
Finally, here’s an example that shows get/set methods alongside other functions in a class:
class BlogPost {
var content = ""
get() {
logAccess(Date())
return field
}
set(s) {
logUpdate(Date(), s)
field = s
}
fun logAccess(d: Date) {
println("logAccess called ...")
//...
}
fun logUpdate(d: Date, s: String) {
println("logUpdate called ...")
//...
}
}