Если вы определяете ваш Maker
интерфейс следующим образом:
interface Maker<out T : Thing>
fun make(): T
}
Тогда ваш Thing
интерфейс может быть определен как:
interface Thing {
val maker: Maker<Thing>
}
Из-за использования out
, реализации могут быть определены как:
class BallMaker : Maker<Ball> {
override fun make(): Ball = TODO("not implemented")
}
class Ball : Thing {
override val maker = BallMaker()
}
Здесь свойство maker
будет иметь тип BallMaker
.Вы также можете использовать:
override val maker: Maker<Ball> = BallMaker()
Если вы предпочитаете выставлять тип интерфейса вместо реализации.
См. Обобщения: in, out, where - Kotlin ProgrammingЯзык для получения дополнительной информации о дженериках в Kotlin.При использовании out
важно знать следующее:
Общее правило: когда параметр типа T
класса C
объявлен out ,это может произойти только в out -положении в элементах C
, но взамен C<Base>
может безопасно быть супертипом C<Derived>
.
Другими словами, если универсальный параметр определен с out
, он может использоваться только в качестве возвращаемых типов, а не типов параметров.Обратное верно для in
.
Конечно, если у вашего Maker
интерфейса есть только один метод, вы можете использовать вместо него тип функции.
interface Thing {
val maker: () -> Thing
}
Это все равно позволит вам:
class Ball : Thing {
// type can be inferred to "() -> Ball" instead in this case
override val maker: () -> Ball = { Ball() }
}
Если вы хотите назвать тип функции, используйте псевдоним type .