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() 
  • Kotlin - Extensión para la class final
  • Las funciones de extensión de Kotlin de repente requieren un nivel de api 24
  • acceso al método de extensión kotlin en otro kt
  • Cómo acceder a una vista desde el layout especificado en headerLayout de NavigationView usando Kotlin en Android
  • Miembro de Kotlin y extensión al mismo time
  • ¿Funciones de extensión Kotlin contra funciones miembro?
  • Mapa Mutable no anulable
  • Funciones de extensión Kotlin por tipo
  • Cómo organizar los methods de extensión de Kotlin
  • ¿Cómo se pueden agregar methods estáticos a las classs de Java en Kotlin?
  • Kotlin class NoClassDefFoundError crash