类标签似乎非常容易使用,但是,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为每个方法定义添加魔法; 我只是问为什么在需要/不可避免的时候不能自动完成.
这个语法:
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支持具体化泛型,一切都会不同......