为什么Scala不会自动"处理"ClassTags?

Eri*_*lun 6 reflection scala

类标签似乎非常容易使用,但是,ClassTag如果不是全部的话,至少在某些情况下,始终可靠地自动插入样板是否在数学上是不可能的?考虑这个例子:

def foo[T: ClassTag] = {
    val cls = classTag[T].runtimeClass.asInstanceOf[Class[T]]
    val myList: Seq[T] = parseList(rawJson, cls) // let's assume parseList a library method that needs to work with a Class instance (e.g. RestFB's fetchConnnection)
    ...
}
Run Code Online (Sandbox Code Playgroud)

斯卡拉为什么不让我写:

def foo[T] = {
    val cls = classOf[T]
    val myList: Seq[T] = parseList(rawJson, cls) // let's assume parseList a library method that needs to work with a Class instance (e.g. RestFB's fetchConnnection)
    ...
}
Run Code Online (Sandbox Code Playgroud)

...并自动将后者转换为前者?

是否存在技术原因,例如,编译器/反射库无法始终可靠地确定类标签的可取性?或者纯粹是一种有意识的设计选择来保持这一点?例如,鼓励程序员首先避免使用类标签以获得更清洁的设计和更好的性能,即使已知在许多情况下它是不可能的?

PS不是在问为什么Scala没有(也不建议它应该)使用泛型类型参数ClassTag每个方法定义添加魔法; 我只是问为什么在需要/不可避免的时候不能自动完成.

Vla*_*eev 4

这个语法:

def foo[T: ClassTag] = ...
Run Code Online (Sandbox Code Playgroud)

事实上是这个的简写:

def foo[T](implicit ev: ClassTag[T]) = ...
Run Code Online (Sandbox Code Playgroud)

这意味着如果ClassTag[T]为每个泛型类型参数提供,那么每个函数都会有附加的隐藏参数,甚至几个。

这当然是完全不希望的。这种方法最显着的缺点之一是使用泛型时几乎破坏了 Java 互操作性:

def foo[T: ClassTag] = ...
Run Code Online (Sandbox Code Playgroud)

想象一下更高级的通用方法和参数。这只是为了能够匹配泛型类型,而这几乎从不需要。

调用 Java 泛型方法也会产生歧义。这里应该调用哪个方法:

val jc = new JavaClass
jc.foo[Int]()
Run Code Online (Sandbox Code Playgroud)

ifJavaClass的定义如下:

def foo[T](implicit ev: ClassTag[T]) = ...
Run Code Online (Sandbox Code Playgroud)

当然,如果Java支持具体化泛型,一切都会不同......