2016-05-10 16 views
1

クラスの汎用タイプを持つラムダフィールドをどのように呼び出すことができますか?何らかの理由で、Example<*>のような汎用クラスへの参照は、元の型(Example<Something>など)をNothingに置き換える受け入れを生成します。 Example<*>を参照するだけで、このようなラムダを呼び出すにはどうすればよいですか?私はこの問題を持っていますKotlin:クラスのジェネリック型を持つラムダフィールドを呼び出すにはどうすればよいですか?

コードベース:https://github.com/Jire/Acelta/tree/master/src/main/kotlin/com/acelta/packet/incoming/packets

私はこのコードにしようとしていますが、あなたは第五行に見ることができるように受け入れるタイプがNothingあるので、私はラムダを呼び出すことはできません。

private val incoming = arrayOfNulls<Packet<*>>(256) 

fun incoming(id: Int, packeteer: Packeteer) { 
    val packet = incoming[id] ?: return 
    packet.receive(packeteer, /* this is type Nothing! */) 
} 
+0

問題をコンパイルして実行している特定のコードを質問自体に追加してください。 – miensol

+0

@miensol使用法が追加されました。 – Jire

+1

最小限の自己完結型の例を作成してください。 'Packet'と' Packeteer'はどう定義されていますか? –

答えて

2

この動作はstar projectionsFoo<*>)はKotlinで働くだけの方法です。

としてはFoo<*>が 値を読み取るためFoo<out TUpper>に相当し、書き込み値のFoo<in Nothing>に、TTUpperを上限 不変型パラメータであるドキュメントFoo<T>について

、で述べています。

あなたがスターの投影をPacket<*>使用している場合、あなたは、このようにあなたが安全に、一般的なパラメータが期待されているその方法(Nothingタイプがある理由です)に任意の値を渡すことはできません、そのジェネリック型について何も知りません。

あなたは、一般的なタイプのために下限を指定するin-projectionを使用することができ、そしてPacket<in SomeType>のために、あなたはメソッドにSomeTypeのインスタンスを渡すことができるようになります。それは投げClassCastExceptionにつながることができますがそれ以外の場合、あなたは、メソッドを呼び出すために未チェックのキャストを使用することができます

private val incoming = arrayOfNulls<Packet<in SomeType>>(256) 

fun incoming(id: Int, packeteer: Packeteer) { 
    val packet = incoming[id] ?: return 
    packet.receive(packeteer, someTypeInstance) 
} 

:これは、Javaで? super Tワイルドカードに似SomeTypeまたはその祖先の一部であるとPacketの実際の型パラメータが必要になります中のどこかに:

(packet as Packet<in SomeType>).receive(packeteer, someTypeInstance) 
+0

この制限を回避するための安全でない方法はありますか? – Jire

+1

@ Jireの場合、 'ClassCastException'がどこかにスローされることを意味するかもしれませんが、安全でないキャストを実行することができます:'(packet as Packet )。receive(packeteer、someTypeInstance) ' – hotkey

関連する問題