Шаг 165.
Основы Kotlin.
Наследование. Создание подкласса

    На этом шаге мы рассмотрим особенности создания подкласса.

    Подкласс обладает всеми чертами наследуемого класса, который также называют родительским классом, или суперклассом.

    Например, жителям NyetHack не помешает городская площадь. Городская площадь - это разновидность комнаты Room со своими особенностями, характерными только для площадей. Например, вывод особого сообщения при входе игрока. Класс TownSquare можно объявить дочерним по отношению к Room, так как у них есть много общего, а затем описать, чем TownSquare отличается от Room.

    Но прежде чем объявлять класс TownSquare, сначала надо изменить класс Room, чтобы его можно было наследовать.

    Не каждый класс, который вы напишете, сможет стать частью иерархии, и даже более того, у них есть ограничение, которое запрещает наследование по умолчанию. Чтобы класс можно было унаследовать, его надо отметить ключевым словом open.

    Добавьте ключевое слово open в Room, чтобы можно было создавать подклассы.

open class Room(val name: String) {
    fun description() = "Room: $name"
    fun load() = "Nothing much to see here..."
}


Рис.1. Делаем класс Room доступным для наследования (Room.kt)

    Теперь, когда Room отмечен как open, создайте класс TownSquare в Room.kt, объявив его подклассом Room через оператор : (двоеточие), как в следующем примере. Добавьте ключевое слово open в Room, чтобы можно было создавать подклассы.

open class Room(val name: String) {
    fun description() = "Room: $name"
    fun load() = "Nothing much to see here..."
}

class TownSquare : Room("Town Square")


Рис.2. Объявление класса TownSquare (Room.kt)

    Объявление класса TownSquare содержит имя класса слева от оператора : и вызов конструктора справа. Вызов конструктора указывает на то, какой родительский конструктор нужно вызвать для создания экземпляра TownSquare и какие аргументы ему передать. В данном случае TownSquare - это версия Room с названием "Town Square".

    Но вы хотите, чтобы у городской площади было не только название. Другой способ добавить отличий подкласса от предка - это переопределение. На предыдущих шагах мы говорили, что свойства представляют данные класса, а функции - его поведение. Подклассы могут переопределять или определять свои реализации для данных и функций.

    Класс Room имеет две функции - description() и load(). Класс TownSquare должен иметь свою реализацию функции load() для выражения радости, когда герой выходит на городскую площадь.

    Переопределите load() в TownSquare, используя ключевое слово override.

open class Room(val name: String) {
    fun description() = "Room: $name"
    fun load() = "Nothing much to see here..."
}

class TownSquare : Room("Town Square")  {
    override fun load() = "The villagers rally and cheer as you enter!"
}


Рис.3. Объявление класса TownSquare (Room.kt)

    Когда вы будете переопределять load(), IntelliJ выразит недовольство, подчеркнув ключевое слово override (рисунок 3).

    IntelliJ, как всегда, права: есть проблема. Ключевым словом open нужно отметить не только класс Room, но также функцию load(), чтобы ее можно было переопределить.

    Сделайте функцию load() в классе Room доступной для переопределения.

open class Room(val name: String) {
    fun description() = "Room: $name"
    open fun load() = "Nothing much to see here..."
}

class TownSquare : Room("Town Square")  {
    override fun load() = "The villagers rally and cheer as you enter!"
}
Файл с проектом можно взять здесь.


Рис.4. Объявление открытой функции (Room.kt)

    Теперь вместо сообщения по умолчанию (Nothing much to see here...) экземпляр TownSquare выведет на экран ликование жителей, когда приходит герой и происходит вызов load().

    На следующем шаге мы продолжим изучение этого вопроса.




Предыдущий шаг Содержание Следующий шаг