Estoy aprendiendo Kotlin y tengo algunos problemas con las funciones. Estoy tratando de crear algo así como una interfaz funcional con un parámetro genérico. En Java crearía algo como esto:
@FunctionalInterface public interface Foo<T extends Bar> { String something(T arg); } Entonces puedo usar esto en otro lugar como este (dado que Person extiende Bar :
Foo<Person> f = p -> p.toString();¿Cómo se escribe esto con Kotlin?
Lo primero que intenté fue usar alias de tipo como este:
typealias Foo<T> = (T) -> StringSin embargo, dejó de funcionar cuando agregué el límite al parámetro de tipo:
typealias Foo<T: Bar> = (T) -> String // Error: Bounds are not allowed on type alias parametersEl segundo enfoque fue escribir una interfaz que extienda el tipo de función:
interface Foo<T: Bar> : (T) -> StringSin embargo, ahora no sé cómo instanciar una función lambda con esto. Funciona cuando creo una clase a partir de ella de esta manera:
class Something: Foo<Person> { override fun invoke(p: Person): String { return p.toString() } } val f = Something()Pero esto es una gran sobrecarga y estoy seguro de que tiene que haber una mejor solución.
Entonces, ¿cómo puedo definir una firma de función que pueda ser reutilizada por muchas funciones que admitan parámetros genéricos con límites en kotlin?
La mayoría de las veces (¿siempre?) basta con definir el tipo de la lambda en el parámetro de la función que la recibe.
Por ejemplo:
open class Bar class Person: Bar() var f = { p: Person -> p.toString() } fun <T : Bar> withFoo(block: (T) -> String) { } fun <T : Bar> otherFoo(block: (T) -> String) { } fun main() { withFoo(f) otherFoo(f) }De la misma manera que la documentación de Kotlin establece: "dado que Kotlin tiene tipos de funciones adecuados, la conversión automática de funciones en implementaciones de interfaces de Kotlin es innecesaria y, por lo tanto, no es compatible".
Consulte https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions