2015-02-03 15 views
44

Ist es möglich, von Java-Code auf Erweiterungsfunktionen zuzugreifen?Zugriff auf die Kotlin-Erweiterungsfunktionen von Java aus

Ich habe die Erweiterungsfunktion in einer Kotlin-Datei definiert.

package com.test.extensions 

import com.test.model.MyModel 

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

Dabei ist MyModel eine (generierte) Java-Klasse. Nun wollte ich es in meinem normalen Java-Code zuzugreifen:

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

jedoch, dass nicht funktioniert. Die IDE erkennt die bar()-Methode nicht und die Kompilierung schlägt fehl.

Was bedeutet Arbeit wird mit mit einer statischen Funktion von Kotlin:

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

unter Verwendung import com.test.extensions.ExtensionsPackage so meine IDE scheint richtig konfiguriert zu sein.

Ich habe die gesamte Java-Interop-Datei von den Kotlin-Dokumenten durchsucht und auch viel gegooglet, aber ich konnte sie nicht finden.

Was mache ich falsch? Ist das überhaupt möglich?

+0

Bitte näher erläutern * funktioniert nicht *? Kompiliert es, löst eine Ausnahme aus oder was? Haben Sie auch 'Paket com.test.extensions.MyModel importieren'? – meskobalazs

+0

@meskobalazs sehe meine bearbeitete Antwort. – Lovis

+0

@meskobalazs auch, ich kann nicht einmal das importieren. Ich kann nur 'com.test.extensions.ExtensionsPackage' importieren. – Lovis

Antwort

60

All Kotlin Funktionen in einer Datei deklariert werden standardmäßig auf statische Methoden in einer Klasse im gleichen Paket und mit einem Namen aus der Kotlin Quelldatei (Anfangsbuchstabe groß geschrieben und „.kt“ Erweiterung ersetzt mit abgeleiteten kompiliert werden das "Kt" Suffix). Für Erweiterungsfunktionen generierte Methoden haben einen zusätzlichen ersten Parameter mit dem Empfängertyp Erweiterungsfunktion.

Wenn Sie es auf die ursprüngliche Frage anwenden, wird der Java-Compiler die Kotlin-Quelldatei mit dem Namen Beispiel sehen. kt

package com.test.extensions 

public fun MyModel.bar(): Int { /* actual code */ } 

, als ob die folgende Java-Klasse

package com.test.extensions 

class ExampleKt { 
    public static int bar(MyModel receiver) { /* actual code */ } 
} 

Wie es passiert nichts mit der erweiterten Klasse von der Java Sicht erklärt wurde, können Sie nicht nur verwenden Punkt-Syntax so den Zugriff auf Methoden. Aber sie sind immer noch aufrufbar als normale Java statische Methoden:

import com.test.extensions.ExampleKt; 

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

Statische Import kann für ExampleKt Klasse verwendet werden:

import static com.test.extensions.ExampleKt.*; 

MyModel model = new MyModel(); 
bar(model); 
+11

Die Namenskonvention für die Klasse mit den Erweiterungen wurde geändert. Bitte aktualisieren Sie die Antwort, um aktuell zu sein. Eine Funktion in der Datei 'Extensions.kt' im Paket' foo.bar' mit der Beispielfunktion 'String.example()' würde von 'foo.bar.ExtensionsKT.example()' –

+0

referenziert, das bedeutet, ich kann ' t verwende die Erweiterung von Kotlin nach Java, wenn ich keine statischen Funktionen schreibe? –

+2

JFYI, Sie können den Namen der Klasse auch mit @file: JvmName (" Utils") ändern. – crgarridos

2

Soweit ich das beurteilen kann, ist dies nicht möglich. Aus meiner Lektüre der Erweiterungen docs, scheint es, dass

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

eine neue Methode mit der Signatur erzeugt

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

Dann ordnet Kotlin diese Funktion, um Anrufe von der Form myModel.bar(), wo, wenn bar() isn‘ t gefunden in der Klasse MyModel sucht es nach statischen Methoden, die mit der Signatur und dem Namensschema übereinstimmen, die es ausgibt. Beachten Sie, dass dies nur eine Annahme aus ihren Anweisungen ist, dass Erweiterungen statisch importiert werden und definierte Methoden nicht überschrieben werden. Ich bin nicht weit genug in ihrer Quelle gekommen, um es sicher zu wissen.

Angenommen, das obige ist wahr, es gibt keine Möglichkeit, dass Kotlin-Erweiterungen aus einfachem Java-Code aufgerufen werden, da der Compiler nur eine unbekannte Methode für ein Objekt und einen Fehler sehen wird.

+2

Diese Antwort ist nicht korrekt, sie können aufgerufen werden. Siehe akzeptierte Antwort. –

+0

Und der Compiler sucht nicht nach statischen Methoden (besonders nicht nach statischen Java-Methoden). Es sucht nach Erweiterungsmethoden, die in derselben Datei deklariert oder importiert wurden. –

7

Kotlin Top-Level-Erweiterungsfunktion als Java statische Methoden kompiliert werden.

Bei Kotlin Extensions.kt in Paketdatei foo.bar enthält:

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

Das Äquivalent von Java-Code wäre:

package foo.bar; 

class ExtensionsKt { 
    public static int bar(String receiver) { 
     ... 
    } 
} 

Es sei denn, das heißt, enthalten Extensions.kt die Linie

@file:JvmName("DemoUtils") 

In diesem Fall wäre die statische Java-Klasse benannte DemoUtils

In Kotlin können Erweiterung Methoden auf andere Arten deklariert werden. (Zum Beispiel als Elementfunktion oder als Erweiterung eines Begleitobjekts.) Ich werde versuchen, diese Antwort zu einem späteren Zeitpunkt zu erweitern.

0

Die anderen Antworten hier decken den Fall ab, dass eine Erweiterungsfunktion auf der obersten Ebene einer Kotlin-Paketdatei aufgerufen wird.

Mein Fall war jedoch, dass ich eine Extension-Funktion innerhalb einer Klasse aufrufen musste. Konkret handelte es sich um ein Objekt.

Die Lösung ist unglaublich einfach.

Alles, was Sie tun müssen, ist Ihre Erweiterungsfunktion als @JvmStatic annotieren, und voila! Ihr Java-Code kann darauf zugreifen und sie verwenden.

1

Sie benötigen Funktionen in den Klassendateien kopieren:

erstellen Kotlin Datei, für die Ex-Utils.

kt

Geben Sie den Code

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

     fun String.getLength(): Int {//kotlin extension function 
      return this.length 
     } 

ODER

class Utils { 
    companion object { 

     @JvmStatic 
     fun getLength(s: String): Int {//init func for java 
      return s.length 
     } 
    } 
} 

fun String.getLength(): Int {//kotlin extension function 
    return Utils.Companion.getLength(this)//calling java extension function in Companion 
} 

In Kotlin Verwendung:

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

In Java verwenden diese:

String str = ""; 
Integer lenth = Utils.getLength(str); 
Verwandte Themen