Шаг 195.
Основы Kotlin.
Интерфейсы и абстрактные классы. Реализация интерфейса

    На этом шаге мы рассмотрим особенности этой реализации.

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

    Используйте оператор :, чтобы объявить, что класс Player реализует интерфейс Fightable.

.   .   .   .
class Player (_name: String,
              override var healthPoints: Int = 100,
              val isBlessed: Boolean,
              private val isImmortal: Boolean) : Fightable {
    .   .   .   .
}


Рис.1. Реализация интерфейса (Player.kt)

    Когда вы добавляете интерфейс Fightable в Player, IntelliJ сообщает об отсутствии свойств и функций. Предупреждение об отсутствии реализации функций и свойств в Player поможет вам соблюсти правила Fightable, а IntelliJ поможет реализовать все необходимое.

    Щелкните правой кнопкой мыши на Player и выберите Generate... | Implement Methods... (рисунок 2) и затем в диалоговом окне Implement Members (рисунок 3) выберите direCount, diceSides и attack(). (О damageRoll поговорим в следующих шагах.)


Рис.2. Выбор Generate... | Implement Methods...


Рис.3. Реализация членов Fightable

    Вы увидите, как был добавлен следующий код в класс Player:


Рис.4. Добавленный код

    Реализации функций, добавленных в Player, пока представлены простыми заглушками. Вам нужно заменить их настоящими реализациями. (Вы могли заметить функцию TODO. Тут она показана в действии, или, скорее, в состоянии ожидания.) Как только вы реализуете эти свойства и функции, Player будет удовлетворять интерфейсу Fightable и сможет участвовать в сражениях.

    Обратите внимание, что во всех реализациях свойств и функций используется ключевое слово override. Это может стать неожиданностью: все-таки вы не заменяете реализацию этих свойств в Fightable. Тем не менее все реализации свойств и функций интерфейса должны быть отмечены словом override.

    С другой стороны, ключевое слово open не нужно при объявлении функций в интерфейсе. Это связано с тем, что все свойства и функции, добавленные в интерфейс, должны, несомненно, иметь модификатор доступа open, иначе их реализация не будет иметь никакого смысла. В конце концов, интерфейс определяет, что нужно реализовать, а как - это уже ответственность классов, реализующих его.

    Замените вызовы TODO в direCount, diceSides и attack() на необходимые значения и функции.

.   .   .   .
class Player (_name: String,
              override var healthPoints: Int = 100,
              val isBlessed: Boolean,
              private val isImmortal: Boolean) : Fightable {
    override val diceCount: kotlin.Int = 3
    override val diceSides: kotlin.Int = 6
    override fun attack(opponent: com.bignerdranch.nyethack.Fightable): kotlin.Int {
        val damageDealt = if (isBlessed) {
            damageRoll * 2
        } else {
            damageRoll
        }
        opponent.healthPoints -= damageDealt
        return damageDealt
        }
    .   .   .   .
}
Файл с проектом можно взять здесь.

    Параметры direCount и diceSides инициализированы целыми числами. Функция attack() извлекает значение свойства damageRoll (которое пока не конкретизировано) и удваивает его, если игрок благословлен. Затем она вычитает результат из свойства healthPoints экземпляра opponent, наличие которого гарантируется независимо от его класса, потому что класс реализует Fightable. В этом заключается красота интерфейса.

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




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