¿Cómo se resuelve la violación de la restricción de límites finitos en Kotlin?

Supongamos que tengo esta statement en Java, está bien.

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

Sin embargo, no está bien en Kotlin, ya que Kotlin tiene restricciones para el parámetro de tipo "cíclico".

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

¿Hay algún enfoque para resolver esto en Kotlin, de modo que pueda tener types generics que dependen el uno del otro?

Es imposible usar solo un parámetro de tipo. Es necesario presentar Self type, que se admite de forma nativa en algunos otros idiomas. Sin embargo, en kotlin deberás introducir el tipo de Self por ti mismo, porque JetBrains rechazó oficialmente la request de agregar self type .

 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 } 

PD: este Self puede inducir más tarde un tipo tediosamente largo. Proceda con precaución.

Deje que G sea un gráfico dirigido cuyos vértices son todos los parameters de tipo de todas las declaraciones de tipo genérico en el progtwig. Para cada tipo de argumento de proyección A en cada tipo genérico B <…> en el set de types de constituyentes de cada tipo en el cierre B del set de los límites superiores declarados de cada tipo, el parámetro T en G agrega un borde de T a U, donde U es el parámetro tipo de la statement de B <…> correspondiente al argumento tipo A. Es un error en time de compilation si el gráfico G tiene un ciclo.

Nota: Un significado intuitivo de un borde X → Y en el gráfico G es "el significado exacto de los límites para el parámetro de tipo X depende de los límites para el parámetro de tipo Y".

Ejemplo:

La siguiente statement no es válida, porque hay un borde T → T, formando un ciclo:

 interface A<T : A<*>> 

El límite A<*> es una proyección con un límite implícito. Si ese límite se hace explícito, el tipo A<*> toma una forma equivalente A<out A<*>> . Del mismo modo, se puede volver a escribir en un equivalente de A<out A<out A<*>>> , y así sucesivamente. En su forma completamente expandida, este límite sería infinito. El propósito de esta regla es evitar tales types infinitos y las dificultades de verificación de tipo asociadas con ellos.

El siguiente par de declaraciones no es válido, porque hay bordes T → S y S → T, formando un ciclo:

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

La siguiente statement no es válida, porque hay bordes K → V y V → K, formando un ciclo:

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

Por otro lado, cada una de las siguientes declaraciones es válida:

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

TODO: Interacción de estos algorithms con types flexibles. TODO: Tipo de import declarado en Java que infringe estas reglas.

Las relaciones de subtipificación se decidirán inductivamente, es decir, deben tener una testing finita.

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

Enlace oficial

  • Kotlin con JPA / Hibernate: sin carga lenta sin `abrir`?
  • La callback OnSuccessListener de Firebase Storage no llama
  • ¿Kotlin apoya la comprensión monádica?
  • Cómo ejecutar el command bash en Kotlin
  • Reflexión de Kotlin: parámetro de tipo desconocido
  • ProGuard hace que Gson devuelva LinkedTreeMap en lugar de mi tipo
  • ¿Qué packages / funciones se importan de manera pnetworkingeterminada en Kotlin?
  • Actualización parcial REST en Spring Boot y Kotlin
  • Error ': app: kaptDebugKotlin' en la versión estable de android studio 3 con la habitación 1 (RC)
  • Kotlin y Android Databinding
  • Convertir matriz de bytes a cadena en Kotlin