super и конструкторы
Часть раздела Объектно-ориентированное программирование путешествия по Kotlin на Coddy. Урок 19 из 57.
super.method() вызывает версию метода суперкласса из переопределения. Подкласс может расширить унаследованное поведение, а не заменить его:
open class Notification(val text: String) {
open fun render() = "[info] $text"
}
class Reminder(text: String, val minutes: Int) : Notification(text) {
override fun render() = super.render() + " (in $minutes min)"
}Внутри main:
println(Notification("backup done").render())
println(Reminder("meeting", 10).render())Вывод:
[info] backup done
[info] meeting (in 10 min)Каждый подкласс должен вызывать конструктор суперкласса. При наличии первичного конструктора вызов является частью заголовка: : Base(arguments), а аргументы можно вычислить из параметров подкласса:
open class Product(val name: String, val price: Int)
class Discounted(name: String, price: Int, val percent: Int) :
Product(name, price * (100 - percent) / 100)Внутри main:
val tea = Discounted("tea", 500, 10)
println("${tea.name} ${tea.price} (${tea.percent}% off)")Вывод:
tea 450 (10% off)Создание выполняется сверху вниз по иерархии: сначала выполняются инициализаторы свойств суперкласса и блоки init, затем — подкласса:
open class Base(name: String) {
init { println("Base init for $name") }
}
class Child(name: String) : Base(name.uppercase()) {
init { println("Child init for $name") }
}Внутри main:
Child("kit")Вывод:
Base init for KIT
Child init for kitКласс без основного конструктора вызывает суперкласс из каждого вторичного конструктора с помощью super(...) или делегирует вызов другому собственному конструктору с помощью this(...):
open class Shape(val name: String)
class Rect : Shape {
val w: Int
val h: Int
constructor(w: Int, h: Int) : super("rect") {
this.w = w
this.h = h
}
constructor(side: Int) : this(side, side)
}Внутри main:
val r = Rect(3)
println("${r.name} ${r.w}x${r.h}")Результат:
rect 3x3Поскольку суперкласс настраивается первым, из его конструктора или init не следует вызывать члены с модификатором open. Переопределённый метод выполняется до того, как собственные свойства подкласса получат свои значения:
open class Base {
init { println("Base sees: ${describe()}") }
open fun describe() = "base"
}
class Child : Base() {
val label = "child"
override fun describe() = "label is $label"
}Внутри main:
Child()Вывод:
Base sees: label is nullЗадание
ЛегкоNotification(text) имеет открытый метод render(), который возвращает [info] text. Завершите реализацию подклассов: render() у Warning возвращает [warn] TEXT, преобразуя текст в заглавные буквы, а Reminder, который также хранит minutes, возвращает результат суперкласса, за которым следует (in 10 min), используя super.
Предоставленный код считывает строки info,text, warn,text или remind,text,10, создаёт соответствующий объект в одном List<Notification> и выводит render() для каждого из них.
Ваш код должен находиться в Notification.kt, Warning.kt и Reminder.kt. В Main.kt находится предоставленный код ввода/вывода, и его нельзя изменять.
Попробуйте сами
fun main() {
// Предоставленный код ввода/вывода: оставьте его как есть
val input = generateSequence(::readLine).toList()
val notes = mutableListOf<Notification>()
for (line in input) {
val p = line.split(",")
notes.add(when (p[0]) {
"warn" -> Warning(p[1])
"remind" -> Reminder(p[1], p[2].toInt())
else -> Notification(p[1])
})
}
for (n in notes) println(n.render())
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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