web-dev-qa-db-fra.com

Comment implémenter cette interface Java dans Kotlin?

Puisque Kotlin n'a pas de primitives, comment cette interface pourrait-elle être implémentée?

public interface A {
  @NotNull Object get(@NotNull Integer i);
  @NotNull Object get(int i);
}

Je ne peux pas changer le code Java car c'est un fichier de classe compilé dans une bibliothèque binaire.

16
ice1000

Si une seule implémentation, comme dans la réponse de @ zsmb13 , ne vous suffit pas et que vous avez besoin d'implémentations distinctes pour les deux méthodes de Kotlin, vous pouvez ajouter une interface intermédiaire remplaçant la méthode acceptant Integer avec un paramètre nullable :

private interface IntermediateA : A {
    override fun get(i: Int?): Any
}

En implémentant cette interface à la place de la A d'origine, le compilateur Kotlin distinguera les deux méthodes, ce qui vous permettra de les remplacer comme suit:

class C : IntermediateA {
    override fun get(i: Int) = "primitive"
    override fun get(i: Int?) = "boxed"
}

val a: A = C()
println(a.get(1)) // primitive
println(a.get(1 as Int?)) // boxed

Si vous aviez accès au code Java, vous pouvez résoudre ce problème en ajoutant une annotation Nullability à la méthode acceptant le type boxed:

Object get(@Nullable Integer i);

Le compilateur Kotlin comprend différents types d’annotations de nullabilité, voici la liste .

14
hotkey

Implémentation d'une seule méthode prenant Int comme paramètre et pouvant être appelée à partir de Kotlin ou de Java.

class B : A {

    override fun get(i: Int): Any {
        return "something"
    }

}

Si vous décompilez le bytecode, vous verrez que le compilateur Kotlin est suffisamment intelligent pour créer les deux méthodes, l'une d'entre elles étant simplement redirigée vers la véritable implémentation.

 Decompiled bytecode example

Un problème possible est que vous ne pouvez pas obliger la méthode à utiliser Int?, et elle plantera avec un NullPointerException sur l'appel .intValue() s'il est appelé depuis Java de la manière suivante:

B b = new B();
Integer i = null;
b.get(i);

Je ne sais pas s'il existe un moyen de résoudre ce cas d'utilisation. 

Edit: la réponse de la touche contient les réponses restantes.

7
zsmb13

À Kotlin, nous pouvons déclarer:

  • primitive int comme: Int
  • boxed int as: Int?

Votre interface peut être simplifiée pour: 

private interface ModifiedA : A {
    override fun get(i: Int?): Any
}

Dans Kotlin, si vous implémentez cette interface modifiée, Kotlin vous fournira deux méthodes pour remplacer. Un pour le type primitif et un autre pour le type en boîte.

class ImplementationOfA : ModifiedA {
    override fun get(i: Int)
    override fun get(i: Int?)
}
1
Avijit Karmakar

J'écris une simple démo en Java.

convertissez-le ensuite en Kotlin avec les plugins Kotlin dans IntelliJ IDEA ou Android Studio.

0
dong sheng