web-dev-qa-db-fra.com

Kotlin: Interface ... n'a pas de constructeur

Je suis en train de convertir une partie de mon code Java en Kotlin et je ne comprends pas très bien comment instancier des interfaces définies dans le code Kotlin. Par exemple, j'ai une interface (définie dans le code Java):

public interface MyInterface {
    void onLocationMeasured(Location location);
}

Et puis plus loin dans mon code Kotlin, je instancie cette interface:

val myObj = new MyInterface { Log.d("...", "...") }

et ça marche bien. Cependant, lorsque je convertis MyInterface en Kotlin:

interface MyInterface {
    fun onLocationMeasured(location: Location)
}

Je reçois un message d'erreur: Interface MyListener does not have constructors lorsque j'essaie de l'instancier - bien qu'il me semble que rien n'a changé à l'exception de la syntaxe. Est-ce que je comprends mal le fonctionnement des interfaces dans Kotlin?

98
Aleph Aleph

Votre code Java repose sur la conversion SAM - une conversion automatique d'un lambda en une interface avec une seule méthode abstraite. La conversion SAM est actuellement non prise en charge pour les interfaces définies dans Kotlin. Au lieu de cela, vous devez définir un objet anonyme implémentant l'interface:

val obj = object : MyInterface {
    override fun onLocationMeasured(location: Location) { ... }
}
169
yole

La meilleure solution consiste à utiliser un typealias à la place de votre interface Java

typealias MyInterface = (Location) -> Unit

fun addLocationHandler(myInterface:MyInterface) {

}

Enregistrez-le comme ceci:

val myObject = { location -> ...}
addLocationHandler(myObject)

ou même plus propre

addLocationHandler { location -> ...}

Invoquez-le comme ceci:

myInterface.invoke(location)

Les 3 options actuelles semblent être:

  • typealias (désordonné lorsqu'il est appelé depuis Java)
  • interface kotlin (désordonné lorsque appelé par kotlin; vous devez créer un objet) C'est un grand pas en arrière pour l'OMI.
  • Interface Java (appel moins facile lorsque kotlin est appelé; lambda a besoin d'un nom d'interface ajouté afin que vous n'ayez pas besoin d'objet; vous ne pouvez pas non plus utiliser lambda en dehors de la convention relative aux parenthèses des fonctions)

Lors de la conversion de nos bibliothèques en Kotlin, nous avons en fait laissé toutes les interfaces dans le code Java, car il était plus simple d'appeler Java de Kotlin que Kotlin de Kotlin.

15
Steven Spungin

Essayez d'accéder à votre interface comme ceci:

 object : MyInterface {
    override fun onSomething() { ... }
}
6
Jéwôm'

si vous avez classe Java comme ceci:

recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(), recyclerView, new RecyclerTouchListener.ClickListener()
        {
              //Your Code
        }));

vous devez convertir ce code de Java à Kotlin comme ceci:

override fun showJozList (list : List<ResponseGetJuzList.Parameter4>) {
        adapter.addData(list)
        jozlist_recycler.addOnItemTouchListener(RecyclerTouchListener(
                activity ,
                jozlist_recycler ,
                object : RecyclerTouchListener.ClickListener
                    {
                          //Your Code
                    }))

convertir interface Java:

new RecyclerTouchListener.ClickListener()

to Interface Kotlin Style:

object : RecyclerTouchListener.ClickListener
6
Adnan Abdollah Zaki