Funciones de extensión para classs genéricas en Kotlin

¿Qué pasa con mi function de extensión a continuación?

class Foo<T> { fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception() init { Foo<Int>() + Foo<String>() // A receiver of type Foo<T> is requinetworking } } 

Actualizar

Me pregunto por qué es diferente a las funciones de extensión regulares, donde T se infiere con éxito como Any y le gustaría lograr el mismo comportamiento, por ejemplo, T para inferirse como Foo <Cualquiera>

 class Foo { fun <T> T.foo(that: T): T = throw Exception() init { "str" foo 42 } } 

El problema está en el corazón de cómo funcionan los generics.

 class Foo { fun <T> T.foo(that: T): T = throw Exception() init { "str" foo 42 } } 

Esto funciona, porque el comstackdor puede encontrar una T que se ajuste tanto a la firma de la function como a los arguments: es Any , y la function se convierte en esta:

 fun Any.foo(that: Any): Any = ... 

Ahora, String es un subtipo de Any , Int es un subtipo de Any , por lo que esta function es aplicable a los arguments.

Pero en tu primer ejemplo:

 class Foo<T> { fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception() init { Foo<Int>() + Foo<String>() // A receiver of type Foo<T> is requinetworking } } 

Es todo diferente. No hay tal T Seamos ingenuos e intentemos Any :

 fun Foo<Any>.plus(that: Foo<Any>): Foo<Any> = ... 

Ahora, Foo es invariante en T , por lo que Foo<Int> no es un subtipo de Foo<Any> , y de hecho no hay ningún tipo T no sea Int que haría que Foo<T> un supertipo de Foo<Int> . Entonces, T debe ser exactamente Int , pero también debe ser exactamente String con la misma lógica (debido al segundo argumento), por lo que no hay solución, y la function no es aplicable.

Podrías hacerlo funcionar haciendo la co-variante de Foo en T :

 class Foo<out T> { fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception() init { Foo<Int>() + Foo<String>() // A receiver of type Foo<T> is requinetworking } } 

Esto impone algunas limitaciones a las posibles firmas de los miembros de Foo , pero si está de acuerdo con ellos, soluciona el problema.

Echa un vistazo a este enlace para get más información: http://kotlinlang.org/docs/reference/generics.html

Su método plus espera que el parámetro tenga el mismo parámetro de tipo genérico T que el receptor. Por lo tanto, no puede agregar un Foo<String> a un Foo<Int> .

Si desea poder agregar todos los types de Foo , debe declarar su function de extensión de la siguiente manera:

 operator fun <T,R> Foo<T>.plus(that: Foo<R>): Foo<T> = throw Exception() 
  • Usa la extensión Kotlin en la class java de Android
  • Kotlin: ¿Cuando la function de extensión oculta la implementación pnetworkingeterminada de la class?
  • Genéricos para RecyclerView.Adapter Android
  • Función de extensión Kotlin en propiedad mutable
  • Problema con el método de extensión en el script de Kotlin
  • lanza Exception en un método con Kotlin
  • Mapa Mutable no anulable
  • Método de extensión de Kotlin como alias para el nombre de método largo?
  • Kotlin: ¿Cómo ejecutar methods de service en el context de una class de transacción?
  • El resultado es el mismo, pero el caso de testing no pasa en la testing unitaria
  • En kotlin, cómo devolver una instancia definida por un parámetro de class genérico