web-dev-qa-db-ja.com

Kotlinメソッドのオーバーロード

この次の宣言はKotlinでは合法です。

fun foo(): String = "foo_1"
fun <T> foo(): T = "foo_2" as T

バイトコードとして、次のようになります。

public final static foo()Ljava/lang/String;

// signature <T:Ljava/lang/Object;>()TT;
// declaration: T foo<T>()
public final static foo()Ljava/lang/Object;

Kotlinからこれらのメソッドの両方を呼び出すことも可能です。

問題は、Javaからそれらのいずれかを呼び出そうとしたときに発生します。

ClassKt.foo()

あいまいな呼び出し。両方の方法が一致します...

このような問題を回避するにはどうすればよいですか?そのような方法をどのように扱うか?サードパーティのktライブラリに同じ問題がある場合はどうなりますか?

上記の例は合成の例です。

7
Sergei Rybalkin

理由は、まずKotlinで動作します...でJavaのような2つのメソッドがあります。

_private static String test() {
    return "";
}

private static <T> T test() {
    return null;
}
_

コンパイル時エラーが発生します。そしてJava devsの場合、これは一種の明白です、これらのメソッドは同じ型の消去を持っているでしょう。しかしこれはルールですこのコードが実行されるjavacによってJVMによってnotによって課されます。したがって、javacは2つのメソッドをのみとして処理しませんオーバーロードとは異なる戻り値の型です。まあ、kotlinは別の言語であり、JVM(有効なバイトコードを期待する)で実行されるため、only戻り値の型がオーバーロードとして異なる。私はまだバイトコードを見て、それがどのように発生するかを理解していません。これは一般的なコードでのみ機能するようですので、コトリンの場合、型消去は少し異なります。

ここで、Java=からこのようなメソッドを呼び出すことが失敗する理由は明らかです。Kotlinは、これに対する適切なソリューションを提供しています:@JvmName("someDistinctName")。これがフードも...まだ、これはブリッジメソッドを作成すると思いますが。

[〜#〜]編集[〜#〜]

_@JvmName_は、バイトコードレベルでメソッドの名前を変更します。

7
Eugene

@ JvmName を使用して、Javaから呼び出されたときにコードを区別できます。

_@JvmName("fooString")
fun foo(): String = "foo_1"

fun <T> foo(): T = "foo_2" as T
_

これにより、衝突を解決するClassKt.fooString()を使用してJavaでStringメソッドを呼び出すことができます。

2
Pawel

簡単な解決策は、Kotlinでヘルパーメソッドを作成し、それを呼び出すだけです。


Javaのみを使用する別の方法は、両方のメソッドでMethodHandleを取得してそれらを使用することです。

MethodHandle MH_fooString = lookup().findStatic(ClassKt.class, "foo", methodType(String.class));
MethodHandle MH_fooT = lookup().findStatic(ClassKt.class, "foo", methodType(Object.class));

String foo = (String) MH_fooString.invokeExact();

ただし、それほど単純ではなく、例外の処理が必要です。

1
Bubletan