Why doesn’t Scala “handle” ClassTags automatically?
Class 标签似乎真的很容易使用,但是,至少在某些情况下(如果不是全部)总是可靠地自动插入 ClassTag 样板在数学上是不可能的吗?考虑这个例子:
|
1
2 3 4 5 |
为什么 Scala 不让我改写:
|
1
2 3 4 5 |
…并自动将后者转换为前者?
这是否有技术原因,例如类标签的可取性不能总是由编译器/反射库可靠地确定?或者它纯粹是一个有意识的设计选择来保持这个明确?例如,鼓励程序员首先避免使用类标签以获得更简洁的设计和更好的性能,即使知道在许多情况下这是不可能的?
附言我不是在问为什么 Scala 不(也不建议它应该)将 ClassTag 魔法添加到具有泛型类型参数的每个方法定义中;我只是在问为什么它不能在需要/不可避免时自动完成。
这个语法:
|
1
|
其实是这个的简写:
这意味着如果为每个泛型类型参数提供了 ClassTag[T],那么每个函数都会有附加的隐藏参数,甚至有几个。
这当然是完全不可取的。这种方法最突出的缺点之一是在使用泛型时几乎破坏了 Java 互操作性:
想象一下更高级的泛型方法和参数。这只是为了能够匹配泛型类型,这几乎不需要。
调用 Java 泛型方法也是模棱两可的。这里应该调用哪个方法:
如果 JavaClass 是这样定义的:
|
1
2 3 4 |
public class JavaClass {
public < T > void foo() { … } public < T > void foo(ClassTag< T > ct) { … } } |
?
当然,如果 Java 支持物化泛型,一切都会不同…
- “为每个泛型类型参数提供”——但我没有说转换应该每次都发生……只有当它\\是不可避免的时候。
- @ErikAllik,这意味着非常不稳定的 API。假设您更改了以前不需要 ClassTag 的代码,因此它开始依赖它。然后,您的 API 的所有用户都可能会中断,而您甚至都不会注意到。当您的泛型方法覆盖另一个方法时,您甚至可以破坏自己的代码 – 突然它将停止覆盖其父方法。此外,这意味着您无法完全控制方法的签名。我当然不喜欢那样。
- 好的,这是一个好点;我会再等一会儿,看看其他人是否能提出一些额外的理由。
来源:https://www.codenong.com/21683420/
