Как разрешить нарушение ограничения конечного ограничения в Котлине?

Предположим, что у меня есть это объявление на Java, все в порядке.

abstract class Start<T extends End> { public T end; } abstract class End<T extends Start> { public T start; } 

Тем не менее, это не нормально в Котлине, поскольку у Котлина есть ограничение на «циклический» параметр типа.

 abstract class Start<T : End<*>> { lateinit var end: T } abstract class End<T : Start<*>> { lateinit var start: T } 

Есть ли какой-нибудь подход к решению этого вопроса в Котлин, так что я могу иметь общие типы, которые зависят друг от друга?

Нельзя использовать только один параметр типа. Необходимо ввести тип Self , который поддерживается на некоторых других языках. Однако в kotlin вам придется вводить сам тип Self , потому что JetBrains официально отклонил запрос на добавление типа «тип» .

 abstract class Start<Self: Start<Self, T>, T: End<T, Self>> { lateinit var end: T } abstract class End<Self: End<Self, T>, T: Start<T, Self>> { lateinit var start: T } 

PS: Это « Self может впоследствии вызывать утомительно длинный тип. Действовать с осторожностью.

Пусть G – ориентированный граф, вершины которого все являются параметрами всех объявлений общего типа в программе. Для каждого проекционного типа-аргумента A в каждом родовом типе B <…> в множестве составных типов каждого типа в B-замыкании множества объявленных верхних границ каждого параметра T в G добавляется ребро из T в U, где U – это параметр типа объявления B <…>, соответствующий аргументу типа A. Это ошибка времени компиляции, если граф G имеет цикл.

Примечание. Интуитивное значение края X → Y в графе G «точное значение границ для параметра типа X зависит от оценок для параметра типа Y».

Пример:

Следующая декларация недействительна, так как существует край T → T, образующий цикл:

 interface A<T : A<*>> 

Оценка A<*> является проекцией с неявной границей. Если эта оценка сделана явной, тип A<*> принимает эквивалентную форму A<out A<*>> . Точно так же его можно переписать в эквиваленте из A<out A<out A<*>>> и так далее. В его полностью расширенной форме эта оценка была бы бесконечной. Цель этого правила – избегать таких бесконечных типов и трудности с проверкой типов, связанные с ними.

Следующая пара объявлений недопустима, поскольку существуют ребра T → S и S → T, образующие цикл:

 interface B<T : C<*>> interface C<S : B<*>> 

Недопустимая следующая декларация, поскольку существуют ребра K → V и V → K, образующие цикл:

 interface D<K: D<K, *>, V: D<*, V>> 

С другой стороны, каждая из следующих деклараций действительна:

 interface A<T : A<T>> interface D<K, V : D<*, V>> 

TODO: Взаимодействие этих алгоритмов с гибкими типами. TODO: импорт типа, объявленного в Java, который нарушает эти правила.

Подтипирование отношений должно решаться индуктивно, т. Е. Должно иметь конечное доказательство.

 interface N<in T> interface A<S> : N<N<A<A<S>>>> 

Официальная ссылка

Intereting Posts
Можно ли выразить kotlin 'с' эквивалентом метода в Scala? Использование Parceler с классом данных Kotlin с конструктором для сериализации Как определить параметры типа для основного конструктора в Котлине? Поведение RxJava Schedulers.immediate () во время модульного тестирования Именование условия if-value для использования в if block Пользовательские представления Android с Kotlin admob banner использует слишком много памяти @ Прежде чем аннотация игнорируется котлином в эспрессо-тесте? Kotlin: зачем использовать абстрактные классы (vs. интерфейсы)? Как правильно выполнять нулевые проверки с использованием функций расширения Kotlin в действии Android Kotlin JPA: Как бороться с инициализацией @OneToOne Невозможно предоставить квалифицированную строку с помощью Dagger2 Возможно ли изменить порядок кнопок навигационной панели в android? Как получить kotlintest для работы с Spring? Есть ли аналог Future.sequence в котлин?