Scala 2.10中的Reified泛型

Lar*_*ann 28 generics scala kotlin ceylon

Scala中缺少具体化的泛型是最让我烦恼的事情,因为如果不使用复杂的结构就无法实现简单的事情.

Kotlin和Ceylon都支持具体化的泛型,因此它绝对有可能在JVM之上这样做.在过去,据说Scala无法在没有JVM变更的情况下支持它们,但现在传闻 Scala 2.10 对于具体化的支持有限.所以我的问题是:

  • 我们可以期待Scala 2.10中的具体化,我是否能够多次实现一般特征?这有多有限?
  • 如果Scala 2.10的具体证明比KotlinCeylon更有限.这是为什么 ?

Dan*_*ral 31

你的论点是有缺陷的.Kotlin还没有发布*,而且Ceylon刚刚发布了它的第一个版本,我将引用其公告中缺少的一件事:

  • 具体化的仿制药

所以,原谅我,但什么实施证明这是可能的吗?事实上,我并没有太多关注Kotlin的承诺,但锡兰所承诺的只是已经提供的内容,而是以透明的方式.

但是,让我们考虑一下您在问题中描述的问题:

trait Handles[E <: Event] {
  def handle(event: E)
}
Run Code Online (Sandbox Code Playgroud)

因此,首先,JVM不提供任何方法来识别接口或类中的类型参数,因此JVM E 无法检查.但是,您可以存储有关E实现的每个对象中的内容的信息Handles,就像您可以在Scala中编写它一样:

abstract class Handles[E <: Event : Manifest] {
  def handle(event: E)
}
Run Code Online (Sandbox Code Playgroud)

接下来,让我们看看方法handle.同样,JVM无法在方法定义中使用类型参数.实现它的唯一方法是将handleaccept Object作为参数:即,键入擦除.

这是交易:handle要从Java调用,它必须被删除类型.并且,如果它是类型擦除,那么它受到您的问题中描述的限制.解决这个问题的唯一方法就是放弃Java兼容性(顺便说一句,这在Ceylon的第一个版本中也是不可用的).

是的,根据Martin Odersky的说法,Scala将在2.10上具有某种特定性.但无论它提供什么(我打赌更透明地使用清单来断言类型相等),这个特殊限制是JVM固有的,并且在不丢弃Java集成的情况下无法克服.

(*)Kotlin现在已经有了一个演示版,它的具体化 - 到目前为止 - 只是捆绑清单和instanceOf测试的语法糖.它仍然受到Scala所有相同的限制.

  • @Lars:不,没有办法在JVM上做适当的reified,而不在JVM,类文件,字节码和语言之间创建一个全新的抽象.尽管两种新语言声称支持具体化的泛型,但这些语言迄今为止没有提供任何内容,除了一些经过美化的实例或测试. (4认同)
  • 虽然我知道这个星球上没有任何事实可以改变你的真实意见,你甚至实际上检查了你的声明一微秒?:-)只是一个例子"错误:一个具有相同名称的方法在字节码级别上重命名为相同的签名.重命名其中一个方法." 请注意"擦除"如何方便地被"具体化"取代?我可以继续,如果编译器不会完全不稳定并且在尝试实现一个简单的接口时崩溃("java.lang.ClassFormatError:类程序_/__ Program__689中的非法字段修饰符"). (4认同)
  • 顶部的单行更新注释与您刚刚留下的注释一样快. (2认同)

Jay*_*ard 8

Kotlin已经为内联函数类型参数确定了泛型,如下所述:https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters.这已经存在于Kotlin已有一段时间了,它们已经被Kotlin生态系统中的许多图书馆所使用.这里的其他答案在提到Kotlin时已经过时了. Kotlin自2016年2月起发布为1.0.

TypeReferenceJackson Kotlin模块中使用的Kotlin中着名的仿制品的例子使用此代码:

public inline fun <reified T: Any> ObjectMapper.readValue(jp: JsonParser): T 
     = readValue(jp, object: TypeReference<T>() {})
Run Code Online (Sandbox Code Playgroud)

基于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>()) }
}
Run Code Online (Sandbox Code Playgroud)