Ссылка на собственный тип в объекте-члене Kotlin - PullRequest
0 голосов
/ 23 июня 2019

У меня есть object s, например:

interface Maker<T : Thing>

interface Thing

Я хочу, чтобы Thing содержал ссылку на его Maker, но я не могу понять, как:

interface Thing {
    val maker: Maker<this::class> // ??
}

чтобы у меня было что-то вроде:

class BallMaker : Maker<Ball>

object Ball : Thing {
    override val maker = BallMaker
}

Как мне этого добиться?

Ответы [ 2 ]

2 голосов
/ 23 июня 2019

С точки зрения Thing его создатель должен быть определен как просто Maker<*>, что означает любой тип создателя вообще.

Вы можете параметризовать Thing с подклассом.

interface Maker<T : Thing<T>> {
}

interface Thing<T : Thing<T>> {
    val maker: Maker<T>
}

class Ball : Thing<Ball> {
    override val maker: Maker<Ball>
}
1 голос
/ 23 июня 2019

Если вы определяете ваш 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 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...