215

Java コードから拡張機能にアクセスすることは可能ですか?

Kotlin ファイルで拡張機能を定義しました。

package com.test.extensions

import com.test.model.MyModel

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

MyModel(生成された) Java クラスはどこにありますか。今、私は通常のJavaコードでそれにアクセスしたかった:

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

しかし、それはうまくいきません。IDE はメソッドを認識せずbar()、コンパイルは失敗します。

何が機能するかは、kotlin の静的関数を使用することです。

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

これを使用import com.test.extensions.ExtensionsPackageすると、IDE が正しく構成されているように見えます。

kotlin docs から Java-interop ファイル全体を検索し、グーグルで検索しましたが、見つかりませんでした。

私は何を間違っていますか?これは可能ですか?

4

10 に答える 10

301

ファイルで宣言されたすべての Kotlin 関数は、デフォルトで、同じパッケージ内のクラスの静的メソッドにコンパイルされ、Kotlin ソース ファイルから派生した名前が付けられます (最初の文字が大文字になり、「.kt 」拡張子が「Kt」サフィックスに置き換えられます)。 . 拡張関数用に生成されたメソッドには、拡張関数のレシーバー型を持つ追加の最初のパラメーターがあります。

元の質問に適用すると、Java コンパイラはexample.ktという名前の Kotlin ソース ファイルを参照します。

package com.test.extensions

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

以下の Java クラスが宣言されたかのように

package com.test.extensions

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

Java の観点からは拡張クラスでは何も起こらないため、ドット構文を使用してそのようなメソッドにアクセスすることはできません。ただし、通常の Java 静的メソッドとして呼び出すことはできます。

import com.test.extensions.ExampleKt;

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

ExampleKt クラスには静的インポートを使用できます。

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

MyModel model = new MyModel();
bar(model);
于 2015-02-06T11:39:59.240 に答える
39

Kotlin の最上位拡張機能は、Java の静的メソッドとしてコンパイルされます。

Extensions.kt以下を含むパッケージ内の指定されたKotlin ファイルfoo.bar:

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

同等の Java コードは次のようになります。

package foo.bar;

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

Extensions.ktつまり、次の行が含まれていない限り

@file:JvmName("DemoUtils")

その場合、Java 静的クラスの名前はDemoUtils

Kotlin では、拡張メソッドを他の方法で宣言できます。(たとえば、メンバー関数として、またはコンパニオン オブジェクトの拡張として。)

于 2016-04-06T13:21:35.617 に答える
-2

次のようにクラスを拡張すると:

fun String.concatenatedLength(str: String): Int {
    return (this.length + str.length)
}

fun f() {
    var len = "one string".concatenatedLength("another string")
    println(len)
}

これは次のようにコンパイルされます。

import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;

public final class ExampleKt {
  public static final int concatenatedLength(@NotNull String $receiver, @NotNull String str) {
    Intrinsics.checkParameterIsNotNull((Object) $receiver, (String) "$receiver");
    Intrinsics.checkParameterIsNotNull((Object) str, (String) "str");
    return $receiver.length() + str.length();
  }

  public static final void f() {
    int len = ExampleKt.concatenatedLength("one string", "another string");
    System.out.println(len);
  }
}

ここにさらにがあります。

于 2018-08-21T15:00:55.783 に答える
-3

私が知る限り、これは不可能です。拡張機能のドキュメントを読んだところ、

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

署名を使用して新しいメソッドを作成します

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

次に、Kotlin はその関数をフォーム の呼び出しにマップします。 クラス内に が見つからないmyModel.bar()場合は、出力するシグネチャと命名スキームに一致する静的メソッドを探します。これは、拡張機能が静的にインポートされ、定義されたメソッドをオーバーライドしないという彼らの声明からの単なる仮定であることに注意してください。私は確かに知るのに十分な情報源に達していません.bar()MyModel

したがって、上記が当てはまると仮定すると、Kotlin 拡張機能をプレーンな古い Java コードから呼び出す方法はありません。コンパイラは、オブジェクトで呼び出された未知のメソッドを認識してエラーを出すだけだからです。

于 2015-02-03T09:14:01.730 に答える