Accéder aux fonctions d’extension Kotlin à partir de Java

Est-il possible d’accéder aux fonctions d’extension à partir du code Java?

J’ai défini la fonction d’extension dans un fichier Kotlin.

package com.test.extensions import com.test.model.MyModel /** * */ public fun MyModel.bar(): Int { return this.name.length() } 

MyModel est une classe Java (générée). Maintenant, je voulais y accéder dans mon code Java normal:

 MyModel model = new MyModel(); model.bar(); 

Cependant, cela ne fonctionne pas. L’EDI ne reconnaîtra pas la méthode bar() et la compilation échoue.

Qu’est-ce que le travail utilise avec une fonction statique de kotlin:

 public fun bar(): Int { return 2*2 } 

en utilisant import com.test.extensions.ExtensionsPackage , mon IDE semble être configuré correctement.

J’ai parcouru tout le fichier d’interopérabilité Java à partir des documents de Kotlin et j’ai aussi beaucoup cherché sur Google, mais je n’ai pas pu le trouver.

Qu’est-ce que je fais mal? Est-ce seulement possible?

Toutes les fonctions de Kotlin déclarées dans un fichier seront compilées par défaut sur des méthodes statiques dans une classe du même paquet et avec un nom dérivé du fichier source de Kotlin (première lettre en majuscule et extension “.kt” remplacée par le suffixe “Kt” ) . Les méthodes générées pour les fonctions d’extension auront un premier paramètre supplémentaire avec le type de récepteur de la fonction d’extension.

Appliquant à la question originale, le compilateur Java verra le fichier source Kotlin avec le nom example.kt

 package com.test.extensions public fun MyModel.bar(): Int { /* actual code */ } 

comme si la classe Java suivante était déclarée

 package com.test.extensions class ExampleKt { public static int bar(MyModel receiver) { /* actual code */ } } 

Comme rien ne se produit avec la classe étendue du sharepoint vue Java, vous ne pouvez pas utiliser la syntaxe point pour accéder à de telles méthodes. Mais ils sont toujours appelables en tant que méthodes statiques Java normales:

 import com.test.extensions.ExampleKt; MyModel model = new MyModel(); ExampleKt.bar(model); 

L’importation statique peut être utilisée pour la classe ExampleKt:

 import static com.test.extensions.ExampleKt.*; MyModel model = new MyModel(); bar(model); 

La fonction d’extension de niveau supérieur de Kotlin est compilée en tant que méthodes statiques Java.

Compte tenu du fichier Kotlin Extensions.kt dans le paquet foo.bar contenant:

 fun Ssortingng.bar(): Int { ... } 

Le code Java équivalent serait:

 package foo.bar; class ExtensionsKt { public static int bar(Ssortingng receiver) { ... } } 

Sauf si, Extensions.kt contenait la ligne

 @file:JvmName("DemoUtils") 

Dans ce cas, la classe Java statique s’appellerait DemoUtils

A Kotlin, les méthodes d’extension peuvent être déclarées autrement. (Par exemple, en tant que fonction membre ou en tant qu’extension d’un object compagnon.) Je vais essayer de développer cette réponse ultérieurement.

Vous devez dupliquer vos fonctions dans les fichiers de classe:

Créer un fichier Kotlin, par exemple pour Utils.kt

Entrer le code

  class Utils { companion object { @JvmStatic fun Ssortingng.getLength(): Int {//duplicate of func for java return this.length } } } fun Ssortingng.getLength(): Int {//kotlin extension function return this.length } 

OU

 class Utils { companion object { @JvmStatic fun getLength(s: Ssortingng): Int {//init func for java return s.length } } } fun Ssortingng.getLength(): Int {//kotlin extension function return Utils.Companion.getLength(this)//calling java extension function in Companion } 

Dans kotlin utiliser:

 val str = "" val lenth = str.getLength() 

En Java, utilisez ceci:

 Ssortingng str = ""; Integer lenth = Utils.getLength(str); 

Autant que je sache, ce n’est pas possible. De ma lecture des extensions de documents, il apparaît que

 public fun MyModel.bar(): Int { return this.name.length() } 

crée une nouvelle méthode avec la signature

 public static int MyModelBar(MyModel obj) { return obj.name.length(); } 

Ensuite, Kotlin mappe cette fonction aux appels de la forme myModel.bar() , où si bar() n’est pas trouvé dans la classe MyModel , il recherche des méthodes statiques correspondant à la signature et au schéma de dénomination qu’il génère. Notez qu’il ne s’agit que d’une supposition de leurs déclarations concernant les extensions imscopes de manière statique et ne remplaçant pas les méthodes définies. Je ne suis pas allé assez loin dans leur source pour savoir avec certitude.

Donc, en supposant que ce qui précède soit vrai, les extensions Kotlin ne peuvent pas être appelées à partir du code java, car le compilateur verra simplement une méthode inconnue appelée sur un object et une erreur.

Les autres réponses couvrent ici le cas de l’appel d’une fonction d’extension située au niveau supérieur d’un fichier de package Kotlin.

Cependant, mon cas était que je devais appeler une fonction d’extension située dans une classe. Plus précisément, je traitais avec un object.

La solution est incroyablement simple .

Tout ce que vous avez à faire est d’annoter votre fonction d’extension en tant que @JvmStatic , et le tour est joué! Votre code Java pourra y accéder et l’utiliser.

Lorsque vous prolongez une classe comme ceci:

 fun Ssortingng.concatenatedLength(str: Ssortingng): Int { return (this.length + str.length) } fun f() { var len = "one ssortingng".concatenatedLength("another ssortingng") println(len) } 

Il comstackra à ceci:

 import kotlin.jvm.internal.Insortingnsics; import org.jetbrains.annotations.NotNull; public final class ExampleKt { public static final int concatenatedLength(@NotNull Ssortingng $receiver, @NotNull Ssortingng str) { Insortingnsics.checkParameterIsNotNull((Object) $receiver, (Ssortingng) "$receiver"); Insortingnsics.checkParameterIsNotNull((Object) str, (Ssortingng) "str"); return $receiver.length() + str.length(); } public static final void f() { int len = ExampleKt.concatenatedLength("one ssortingng", "another ssortingng"); System.out.println(len); } } 

Il y a plus d’ exemples ici .