Kotlin:我怎样才能调用一个具有类的泛型类型的lambda字段?

时间:2016-05-10 06:40:02

标签: generics lambda kotlin

如何调用具有类的泛型类型的lambda字段?出于某种原因,对Example<*>这样的通用类的引用会产生一个接受,用Example<Something>替换原始类型(如Nothing)。如何仅通过引用Example<*>

来调用这样的lambda

Codebase我遇到了这个问题:https://github.com/Jire/Acelta/tree/master/src/main/kotlin/com/acelta/packet/incoming/packets

我正在尝试使用此代码,但正如您在第5行所看到的,我无法调用lambda,因为接受类型为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! */)
}

1 个答案:

答案 0 :(得分:2)

此行为正是star projectionsFoo<*>)在Kotlin中的作用。

正如文档中所述

  

对于Foo<T>,其中T是带上部的不变类型参数   绑定TUpperFoo<*>相当于Foo<out TUpper>进行阅读   值和Foo<in Nothing>用于写入值。

如果你使用星形投影Packet<*>,你对它的泛型类型一无所知,因此你不能安全地将任何值传递给期望泛型参数的方法(这就是Nothing类型存在的原因)

您可以使用in-projection为通用类型指定下限,对于Packet<in SomeType>,您可以将SomeType的实例传递到方法。这将要求Packet的实际类型参数为SomeType或其某些祖先,类似于Java中的? super T通配符:

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

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

否则,您可以使用未经检查的强制转换来调用该方法,尽管它可能会导致ClassCastException被抛出到某处:

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