На этом шаге мы рассмотрим особенности такого объявления.
Обобщенный тип - это класс, конструктор которого принимает аргументы любого типа. Начнем с объявления своего обобщенного типа.
Откройте проект Sandbox и добавьте новый файл с именем Generics.kt. Внутри Generics.kt объявите класс LootBox с параметром обобщенного типа для его содержимого, а также с private-свойством loot, которому присваивается аргумент item - награда.
class LootBox<T>(item: T) { private var loot: T = item }
Рис.1. Создание обобщенного типа (Generics.kt)
Вы объявляете класс LootBox и делаете его обобщенным, указывая параметр обобщенного типа Т в угловых скобках (< >) для использования с классом. Параметр обобщенного типа Т служит заполнителем для определения типа награды.
Главный конструктор класса LootBox принимает награду любого типа (item: T) и присваивает его значение private-свойству loot, также имеющему тип T.
Обратите внимание, что параметр обобщенного типа часто обозначается единственной буквой Т, сокращенно от "type" (тип) слова "тип", хотя точно так же можно использовать любую букву или слово. Мы предлагаем использовать Т, так как это распространенная форма записи и в других языках, в которых есть обобщения, следовательно, использование этой записи будет удобно для чтения.
Время опробовать новый класс LootBox. Добавьте функцию main(), объявите пару видов наград и создайте пару экземпляров каждой награды в сундуке (loot box).
class LootBox<T>(item: T) { private var loot: T = item } class Fedora(val name: String, val value: Int) class Coin(val value: Int) fun main(args: Array<String>) { val lootBoxOne: LootBox<Fedora> = LootBox( Fedora("a generic-looking fedora", 15)) val lootBoxTwo: LootBox<Coin> = LootBox(Coin(15)) }
Рис.2. Объявление сундуков с наградой (Generics.kt)
Вы создали два вида наград (шляпы (fedora) и монеты (coins); и то и другое - это очень желанные награды) и два сундука, чтобы хранить их.
Так как вы сделали класс LootBox обобщенным, можно использовать только одно объявление класса для поддержки разных сундуков с наградами: одних - только со шляпами, других - только с монетами и т. д.
Обратите внимание на объявления переменных LootBox:
val lootBoxOne: LootBox<Fedora> = LootBox( Fedora("a generic-looking fedora", 15)) val lootBoxTwo: LootBox<Coin> = LootBox(Coin(15))
Угловые скобки в объявлении типа переменной указывают, какой тип награды может хранить конкретный экземпляр LootBox.
Обобщенные типы, как и другие типы в Kotlin, поддерживаются механизмом автоматического определения типов. Для иллюстрации мы явно указали типы, но их можно опустить, так как каждая переменная инициализируется значением конкретного типа. В своем коде вы обычно отбрасываете информацию о типе, если она не нужна. Так что не стесняйтесь и смело удаляйте ее, если вам захочется.
На следующем шаге мы рассмотрим обобщенные функции.