Custom Accessors
Part of the Object Oriented Programming section of Coddy's Kotlin journey. Lesson 7 of 57.
Every Kotlin property has a getter, and every var also has a setter. By default they read and write a stored value. A custom getter computes the value on every read instead:
class Rectangle(var width: Int, var height: Int) {
val area: Int
get() = width * height
}Inside main:
val r = Rectangle(3, 4)
println(r.area)
r.width = 10
println(r.area)Output:
12
40A custom setter runs code whenever the property is assigned. Inside it, value is the assigned value and field is the stored value behind the property, the backing field:
class Thermostat {
var target = 20
set(value) {
field = value.coerceIn(10, 30)
}
}Inside main:
val t = Thermostat()
t.target = 42
println(t.target)
t.target = 18
println(t.target)Output:
30
18Inside an accessor, use field, not the property name: writing target = value inside the setter of target would call the setter again, forever:
var target = 20
set(value) {
// target = value // calls this setter again: infinite recursion
field = value // stores the value
}A setter is also the place to react to changes, for example to count or log them:
class Player(name: String) {
var changes = 0
private set
var name = name
set(value) {
field = value.trim()
changes++
}
}Inside main:
val p = Player("ada")
p.name = " Ada "
p.name = "Ada L."
println("${p.name} after ${p.changes} changes")Output:
Ada L. after 2 changesChallenge
EasyComplete the class Circle(radius: Double). radius is a var whose setter stores negative values as 0. Add the read-only properties diameter and area (π r² with Math.PI) with custom getters, and label, which returns r=2.0 d=4.0 a=12.57 with the area rounded to two decimals ("%.2f".format(area)).
The supplied code reads one radius per line, prints label, then doubles the radius of the last circle and prints label again, so the values must follow the radius.
Your code goes in Circle.kt. Main.kt holds the supplied input/output code and cannot be edited.
Try it yourself
fun main() {
// Supplied input/output code: keep it as it is
val input = generateSequence(::readLine).toList()
var last = Circle(0.0)
for (line in input) {
last = Circle(line.toDouble())
println(last.label)
}
last.radius *= 2
println(last.label)
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Classes and Objects
Working With FilesDefining ClassesPrimary Constructorsinit Blocks and ValidationSecondary ConstructorsRecap - Library Card4Inheritance
Open Classes and SubclassesOverriding Memberssuper and ConstructorsAbstract ClassesRecap - Staff Directory2Properties and Encapsulation
Custom AccessorsVisibility ModifiersPrivate Setterslazy and lateinitRecap - Bank Account5Interfaces
Declaring InterfacesDefault MethodsMultiple InterfacesInterfaces as TypesRecap - Payment Methods8Generics
Generic FunctionsGeneric ClassesType ConstraintsVariance With in and outRecap - Priority Queue11Project: Library Management
Books and MembersBorrowing BooksPractice on your own: Kotlin playground