На этом шаге мы приведем некоторые замечания, касающиеся приведения типов.
Проверка типа не всегда возвращает полезный ответ. Например, параметр any в функции printIsSourceOfBlesings() говорит нам о том, что передаваемый аргумент будет иметь тип Any, но тип Any не уточняет, что с этим аргументом можно делать.
Приведение типа позволяет обращаться к объекту так, как будто он - экземпляр другого типа. Это позволяет манипулировать объектом, как если бы его тип был объявлен явно (например, вызывать его функции).
В функции printIsSourceOfBlesings() условный оператор проверяет тип аргумента any, сравнивая его с типом Player. Если условие не выполняется, управление передается в ветвь else.
Код в ветви else ссылается на переменную name:
fun printIsSourceOfBlessings(any: Any) { val isSourceOfBlessings = if (any is Player) { any.isBlessed } else { (any as Room).name == "Fount of Blessings" } println("$any is a source of blessings: $isSourceOfBlessings") }
Оператор as обозначает приведение типа. Он говорит нам: "Чтобы выполнить это выражение, переменную any следует считать экземпляром типа Room". Выражение в данном случае - это ссылка на свойство name класса Room, значение которого сравнивается со строкой "Fount of Blessings".
Приведение типов - это сила, а с силой приходит ответственность: применять его необходимо осторожно. Примером безопасного применения может служить приведение значения типа Int к более точному числовому типу, например Long.
Приведение в printIsSourceOfBlesings() работает, но оно небезопасно. Почему? Room, Player, TownSquare - это все классы в NyetHack, поэтому можно предположить, что если any имеет тип, отличный от Player, значит, он имеет тип Room.
На данный момент это так. Но что будет, если мы добавим новый класс в NyetHack?
Ваше приведение не сработает, если тип экземпляра несовместим с типом, к которому его надо привести. Например, строка String не имеет ничего общего с Int, поэтому приведение String к Int вызовет исключение ClassCastException, которое может вызвать сбой программы. (Помните, что приведение и преобразование - это разные вещи. Некоторые строки можно преобразовать в целые числа, но нельзя строковый тип String привести к числовому типу Int).
Оператор приведения типа позволяет попытаться привести любую переменную к любому типу, но ответственность за результат приведения полностью лежит на вас. Если операция приведения типа может быть небезопасной, заключите ее в блок try/catch. Тем не менее лучше избегать приведения типов, если вы не уверены, что оно пройдет успешно.
На следующем шаге мы рассмотрим умное приведение типа.