На этом шаге мы рассмотрим создание своих методов и свойств.
Подклассы могут не только переопределять свойства и функции суперклассов, но и объявлять свои.
Городская площадь NyetHack, например, отличается от других комнат наличием колоколов, возвещающих о важных событиях. Добавьте в TownSquare private-функцию ringBell() и private-переменную с именем bellSound. Свойство bellSound содержит строку, которая описывает звон колоколов, а ringBell(), вызываемая в load(), возвращает эту строку, чтобы объявить о вашем приходе на городскую площадь.
open class Room(val name: String) { protected open val dangerLevel = 5 fun description() = "Room: $name\n" + "Danger level: $dangerLevel" open fun load() = "Nothing much to see here..." } class TownSquare : Room("Town Square") { override val dangerLevel = super.dangerLevel - 3 private var bellSound = "GWONG" override fun load() = "The villagers rally and cheer as you enter!\n${ringBell()}" private fun ringBell() = "The bell tower announces your arrival. $bellSound" }
Рис.1. Добавление нового свойства и функции в подкласс (Room.kt)
Класс TownSquare включает свойства и функции, объявленные и в TownSquare, и в Room. Однако Room содержит не все свойства и функции, объявленные в TownSquare, и поэтому не имеет доступа к ringBell().
Протестируйте функцию load(), обновив переменную currentRoom в Game.kt, чтобы создать экземпляр TownSquare.
import Player import Room import TownSquare fun main() { val player = Player("Madrigal") player.castFireball() var currentRoom: Room = TownSquare() println(currentRoom.description()) println(currentRoom.load()) . . . . }
Рис.2. Вызов реализации функции подкласса (Game.kt)
Запустите Game.kt снова. В консоли появятся следующие строки:
A glass of Fireball springs into existence. (x2) Room: Town Square Danger level: 2 The villagers rally and cheer as you enter! The bell tower announces your arrival. GWONG (Aura: GREEN) (Blessed: YES) Madrigal of Sanorith is in excellent condition!
Рис.3. Результат работы приложения
Обратите внимание, что переменная currentRoom в Game.kt до сих пор имеет тип Room, несмотря на то что сам экземпляр имеет тип TownSquare, а его функция load() существенно изменилась по сравнению с реализацией в Room. Вы явно указали тип Room для currentRoom, поэтому она может ссылаться на комнату любого типа, даже если вы присвоите currentRoom объект, возвращаемый конструктором TownSquare.
Так как TownSquare - подкласс Room, это допустимый синтаксис.
На следующем шаге мы закончим изучение этого вопроса.