Cómo kotlin hace que setOnClickListener acepte funciones como parámetro

En kotlin, podemos usar setOnClickListener() así:

 view.setOnClickListener { println("Hello") } 

Pero si defino mi propia interfaz, sólo puedo pasar un objeto anónimo como este:

 obj.setMyListener(object: MyListener() { ... }) 

Me pregunto cómo hacen setOnClickListener() aceptar una función en lugar de un objeto anónimo.

De acuerdo con las documentaciones de Kotlin sobre interoperabilidad Java , para una interfaz funcional definida en Java, puede utilizar una conversión SAM.

Al igual que Java 8, Kotlin soporta las conversiones SAM. Esto significa que los literales de función de Kotlin pueden convertirse automáticamente en implementaciones de interfaces Java con un solo método no predeterminado, siempre y cuando los tipos de parámetros del método de interfaz coincidan con los tipos de parámetros de la función Kotlin.

 val runnable = Runnable { println("This runs in a runnable") } val executor = ThreadPoolExecutor() // Java signature: void execute(Runnable command) executor.execute { println("This runs in a thread pool") } 

Sin embargo, Kotlin tiene tipos funcionales, por lo tanto, la conversión SAM no funciona para las interfaces definidas en Kotlin:

También tenga en cuenta que esta función sólo funciona para Java interop; Ya que Kotlin tiene tipos de funciones adecuadas, la conversión automática de funciones en implementaciones de interfaces Kotlin es innecesaria y, por lo tanto, no es compatible.


Soluciones posibles:

  1. Defina la interfaz en Java. Útil si se trata de una biblioteca / código que puede utilizarse desde un código Java.
  2. Haga que el método reciba una función como argumento:

     // Example listener receives a bool and return unit. fun setMyListener(listener: (isChecked: Bool) -> Unit) { ... } // Usage: obj.setMyListener { isChecked -> } 
  3. Usar alias de tipo (sólo admitido en Kotlin 1.1+):

     typealias MyListener = (Bool) -> Unit fun setMyListener(listener: MyListener) { ... } 
  • Vinculación de datos de Android y Kotlin
  • La instancia de fragmento se conserva pero el fragmento secundario no se vuelve a conectar
  • Uso de la función "con"
  • Muchos módulos pequeños, o pocos módulos grandes para el mejor rendimiento de la construcción?
  • Cómo setOnEditorActionListener con Kotlin
  • HttpLoggingInterceptor no registra con retrofit 2
  • ¿Cómo llamar a una función después de la demora en Kotlin?
  • Utilizar extensión de Kotlin en la clase android java
  • Kotlin - cuando la expresión con el tipo de retorno de la función
  • Kotlin kapt y componentes de arquitectura android fallan
  • Json a clases de datos kotlin
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.