Пользовательские аксессоры
Часть раздела Объектно-ориентированное программирование путешествия по Kotlin на Coddy. Урок 7 из 57.
У каждого свойства Kotlin есть геттер, а у каждого var также есть сеттер. По умолчанию они считывают и записывают сохранённое значение. Пользовательский геттер вместо этого вычисляет значение при каждом чтении:
class Rectangle(var width: Int, var height: Int) {
val area: Int
get() = width * height
}Внутри main:
val r = Rectangle(3, 4)
println(r.area)
r.width = 10
println(r.area)Вывод:
12
40Пользовательский сеттер выполняет код при каждом присваивании свойству. Внутри него value — это присваиваемое значение, а field — сохранённое значение, стоящее за свойством, то есть резервное поле:
class Thermostat {
var target = 20
set(value) {
field = value.coerceIn(10, 30)
}
}Внутри main:
val t = Thermostat()
t.target = 42
println(t.target)
t.target = 18
println(t.target)Вывод:
30
18Внутри аксессора используйте field, а не имя свойства: запись target = value внутри сеттера target вызвала бы этот сеттер снова и снова, что привело бы к бесконечной рекурсии:
var target = 20
set(value) {
// target = value // вызывает этот сеттер снова: бесконечная рекурсия
field = value // сохраняет значение
}Сеттер также является местом для реакции на изменения, например для их подсчёта или журналирования:
class Player(name: String) {
var changes = 0
private set
var name = name
set(value) {
field = value.trim()
changes++
}
}Внутри main:
val p = Player("ada")
p.name = " Ada "
p.name = "Ada L."
println("${p.name} after ${p.changes} changes")Вывод:
Ada L. after 2 changesЗадание
ЛегкоЗавершите класс Circle(radius: Double). radius — это var, сеттер которого сохраняет отрицательные значения как 0. Добавьте доступные только для чтения свойства diameter и area (π r² с использованием Math.PI) с пользовательскими геттерами, а также label, который возвращает r=2.0 d=4.0 a=12.57, округляя площадь до двух знаков после запятой ("%.2f".format(area)).
Предоставленный код считывает по одному радиусу в каждой строке, выводит label, затем удваивает радиус последнего круга и снова выводит label, поэтому значения должны соответствовать радиусу.
Ваш код должен находиться в Circle.kt. В Main.kt содержится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
fun main() {
// Предоставленный код ввода/вывода: оставьте его как есть
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)
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовПервичные конструкторыБлоки init и валидацияВторичные конструкторыПовторение — читательский билет4Наследование
Открытые классы и подклассыПереопределение членовsuper и конструкторыАбстрактные классыПовторение — каталог сотрудников7Специальные классы
Классы данныхКлассы перечисленийЗапечатанные иерархииequals, hashCode, toStringПовторение — трекер заказов10Паттерны проектирования. Часть 2
Делегирование с помощью byПаттерн декораторПаттерн строительПаттерн состояние2Свойства и инкапсуляция
Пользовательские аксессорыМодификаторы видимостиПриватные сеттерыlazy и lateinitПовторение — банковский счёт5Интерфейсы
Объявление интерфейсовМетоды по умолчаниюМножественные интерфейсыИнтерфейсы как типыПовторение — способы оплаты8Обобщения
Обобщённые функцииОбобщённые классыОграничения типовВариативность с in и outПовторение — очередь с приоритетом11Проект: Управление библиотекой
Книги и читателиВыдача книг3Объекты и компаньоны
Объявления объектовОбъекты-компаньоныКонстанты с constОбъектные выраженияПовторение — билетная касса6Полиморфизм
Динамическая диспетчеризацияПроверка типов и умные приведения типовwhen с типамиФункции-расширенияПовторение — смотритель зоопарка9Паттерны проектирования. Часть 1
Паттерн «Одиночка»Фабричный паттернПаттерн «Наблюдатель»Паттерн «Стратегия»Потренируйтесь самостоятельно: Песочница Kotlin