На этом шаге мы рассмотрим задание таких ограничений.
Допустим, вы бы хотели гарантировать, что в сундук можно складывать только награды, а не что-нибудь еще. Можете указать ограничение обобщенного типа для решения конкретно этой задачи.
Для начала объявим классы Coin и Fedora как подклассы нового суперкласса Loot.
class LootBox<T>(item: T) { var open = false private var loot: T = item fun fetch(): T? { return loot.takeIf { open } } fun <R> fetch(lootModFunction: (T) -> R): R? { return lootModFunction(loot).takeIf { open } } } open class Loot(val value: Int) class Fedora(val name: String, value: Int): Loot(value) class Coin(value: Int): Loot(value)
Рис.1. Добавление суперкласса (Generics.kt)
Теперь добавим ограничение в объявление параметра обобщенного типа LootBox, чтобы только наследники класса Loot могли использоваться с LootBox.
class LootBox<T : Loot>(item: T) {
. . . .
}
Рис.2. Ограничение параметра обобщенного типа суперклассом Loot (Generics.kt)
В примере вы добавили ограничение для обобщенного типа Т, определив его как :Loot. Теперь в сундук можно положить только те награды, которые являются наследниками класса Loot.
Возможно, у вас возник вопрос: зачем вообще нужен параметр Т? Почему просто не использовать тип Loot? Параметр Т позволяет обращаться к награде определенного типа и одновременно допускает помещать в сундук награды любого вида. То есть сундук LootBox будет хранить награду не типа Loot, а, например, типа Fedora. И конкретный тип Fedora будет определяться с помощью Т.
Объявив тип награды как Loot, вы точно так же смогли бы поместить в сундук только наследников Loot, но информация о том, что в сундуке хранится награда Fedora, была бы утрачена. Использование конкретного типа Loot, например, не позволило бы скомпилировать следующий код:
val lootBox<Loot>: LootBox<Fedora> = LootBox( Fedora("a dazzling fuschia fedora", 15)) val fedora: Fedora = lootBox.item // Несовпадение типов - Требуется: Fedora, // Имеется: Loot }
И вы уже не узнаете, что сундук LootBox хранит что-то отличное от Loot. Используя ограничение типов, возможно ограничить содержимое сундука до Loot и сохранить подтип награды в сундуке.
На следующем шаге мы рассмотрим ключевые слова vararg и get.