generics - reified - kotlin parameter
¿Cómo puedo restringir un parámetro de función de extensión de Kotlin para que sea el mismo que el tipo extendido? (3)
Quiero escribir un método de extensión en un tipo genérico T, donde el tipo coincidente restringe un parámetro de método.
Quiero que esto compile:
"Hello".thing("world")
Pero no esto, ya que 42 no es una cadena:
"Hello".thing(42)
Esta definición no funciona, porque T cumple con T
fun <T> T.thing(p: T) {}
Como lo mencionó @Alexander Udalov , no es posible hacerlo directamente, pero existe una solución alternativa en la que se define el método de extensión en otro tipo, por lo que:
data class Wrapper<T>(val value: T)
val <T> T.ext: Wrapper<T> get() = Wrapper(this)
fun <T> Wrapper<T>.thing(p: T) {
println("value = $value, param = $p")
}
Con lo anterior se compila lo siguiente:
"abc".ext.thing("A")
pero el siguiente falla
"abc".ext.thing(2)
con:
Kotlin: Type inference failed: Cannot infer type parameter T in fun <T> Wrapper<T>.thing(p: T): Unit
None of the following substitutions
receiver: Wrapper<String> arguments: (String)
receiver: Wrapper<Int> arguments: (Int)
can be applied to
receiver: Wrapper<String> arguments: (Int)
Según lo sugerido por @hotkey, parece que debería ser posible evitar la necesidad del tipo Wrapper
explícito con la siguiente propiedad de extensión:
val <T> T.thing: (T) -> Any? get() = { println("extension body") }
Y luego "abc".thing("A")
como "abc".thing("A")
pero también falla . Sorprendentemente, lo siguiente compila "abc".thing.invoke("A")
Mejorar la solución de @miensol y hacerla visualmente idéntica a la llamada de función:
val <T> T.foo: (T) -> SomeType get() = { other -> ... }
Esta es una propiedad de extensión que proporciona un lambda, que puede invocarse inmediatamente con un argumento del mismo tipo T
como este:
"abc".foo(1) // Fail
"abc".foo("def") // OK
Desafortunadamente, youtrack.jetbrains.com/issue/KT-13965 que le impide escribir "abc".thing("abc")
, pero cualquiera de "abc".thing.invoke("abc")
y ("abc".thing)("abc)
funciona bien y filtra las llamadas sin cadenas.