¿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

  • Agregar idioma al keyboard sin abrir la configuration
  • ¿Cómo leer JSON desde Url usando kotlin Android?
  • Kotlin - Persistir MutableList en ShanetworkingPreferences
  • Invierte el order de las palabras en una cadena en Kotlin
  • ¿Puedo aplicar la function infija dentro de la propia class sin `this`?
  • ¿Cómo puedo ejecutar una sola testing de Android usando Kotlin?
  • Choque de extensión Kotlin
  • Cómo inicializar una variable de reference en Kotlin
  • ¿Cómo prohibir las llamadas a funciones con un cierto subtipo de un tipo de parámetro?
  • ¿Qué es la testing (0) en este fragment de kotlinlang.org?
  • ¿Hay algún error sobre selectionKey.attachment () en java nio?