Scala中缺少具体化的泛型是最让我烦恼的问题,因为simple things如果不使用复杂的结构就无法实现。
Kotlin和Ceylon都支持具体化的泛型,所以它绝对可以在JVM之上这样做。在past中,据说Scala无法在没有JVM更改的情况下支持它们,但现在Scala 2.10 rumored对于具体化的支持有限。所以我的问题是:
答案 0 :(得分:31)
你的论点存在缺陷。 Kotlin尚未发布*,Ceylon刚刚发布了第一个版本,我将引用their announcement中缺少的一个内容:
- reified generics
那么,请原谅,但 实施证明它有可能吗?事实上,我并没有太多关注Kotlin的承诺,但 Ceylon 有希望的只是已经提供的内容,但是以透明的方式。
但是让我们考虑你在问题中描述的问题:
trait Handles[E <: Event] {
def handle(event: E)
}
因此,首先,JVM没有提供任何方法来识别接口或类中的类型参数,因此JVM无法检查E
。但是,您可以在实现E
的每个对象中存储有关Handles
代表什么的信息,就像您可以在Scala中编写它一样:
abstract class Handles[E <: Event : Manifest] {
def handle(event: E)
}
接下来,让我们看一下方法handle
。同样,JVM无法在方法定义中使用类型参数。实现它的唯一方法是让handle
接受Object
作为参数:即,键入擦除。
这是交易:要使handle
可以从Java调用,它必须被删除类型。并且,如果它是类型擦除,那么它受到您的问题中描述的限制。解决这个问题的唯一方法就是放弃Java兼容性(顺便说一句,这在Ceylon的第一个版本中也不可用)。
是的,根据Martin Odersky的说法,Scala将会在2.10上具有某种特定性。但无论它提供什么(我打赌更透明地使用清单来断言类型相等),这个特殊的限制是JVM固有的,并且在不放弃Java集成的情况下无法克服。
(*)Kotlin现在有一个演示版,它的具体化 - 到目前为止 - 只是捆绑清单和instanceOf测试的语法糖。它仍然受到Scala所有相同的限制。
答案 1 :(得分:8)
Kotlin已经为内联函数类型参数确定了泛型,如下所示:https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters。这已经存在于Kotlin已有一段时间了,它们已经被Kotlin生态系统中的许多图书馆所使用。这里的其他答案在提到Kotlin时已经过时了。 Kotlin自2016年2月起已发布为1.0。
在Jackson Kotlin module中使用的Kotlin(杰克逊着名的TypeReference
)中的具体化仿制药示例使用此代码:
public inline fun <reified T: Any> ObjectMapper.readValue(jp: JsonParser): T
= readValue(jp, object: TypeReference<T>() {})
基于Kotlin的Injekt库也是如此:
public inline fun <reified T: Any> fullType(): FullTypeReference<T>
= object:FullTypeReference<T>(){}
public inline fun <reified T : Any> injectLazy(): Lazy<T> {
return lazy { Injekt.get(fullType<T>()) }
}
答案 2 :(得分:3)
根据安德烈·布雷斯拉夫在this页上所说的话,科特林没有具体的类型:
“是的,类对象在类对象中不可用”