Scala 2.10中的Reified泛型

时间:2011-12-22 14:33:16

标签: generics scala ceylon kotlin

Scala中缺少具体化的泛型是最让我烦恼的问题,因为simple things如果不使用复杂的结构就无法实现。

Kotlin和Ceylon都支持具体化的泛型,所以它绝对可以在JVM之上这样做。在past中,据说Scala无法在没有JVM更改的情况下支持它们,但现在Scala 2.10 rumored对于具体化的支持有限。所以我的问题是:

  • 我们可以期待Scala 2.10中的具体化,例如我是否能够实现generic trait multiple times?这有多有限?
  • 如果Scala 2.10的具体证明比KotlinCeylon更有限。那是为什么?

3 个答案:

答案 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页上所说的话,科特林没有具体的类型:

  

“是的,类对象在类对象中不可用”