我已经阅读了一些教程,包括有关协变类型方法签名的主要 Scala 文档。假设我有以下抽象类:
abstract class List[+A] {
def head: A
def tail: List[A]
def isEmpty: Boolean
def add[B >: A](element: B): List[B]
protected def printElements: String
override def toString: String = "[" + printElements + "]"
}
我的问题涉及 add()
方法的签名。为什么有必要这样声明呢?我们传入的参数是 A 的父类(super class)型。这解决了什么问题?我试图从直觉层面理解这一点。
最佳答案
正式解释
给定
abstract class List[+A] {
def add(element: A): List[A]
}
"This program does not compile, because the parameter element in
add
is of typeA
, which we declared covariant. This doesn’t work because functions are contravariant in their parameter types and covariant in their result types. To fix this, we need to flip the variance of the type of the parameter element inadd
.
We do this by introducing a new type parameterB
that hasA
as a lower type bound".
-- reference.
直观的解释
在这个例子中,如果你添加
一些东西到List:
它必须是 A
- 在这种情况下 List 仍然是 List[A]
。
或者它必须是A
的任何子类型 - 在这种情况下,元素被向上转换 为A
,并且< strong>List 仍然是 List[A]
。
或者,如果它是另一种类型 B
,那么它必须是 A
的父类(super class)型 - 在本例中是 List被升级为 List[B]
。 (注意:因为 Any
只是所有内容的父类(super class)型,在最坏的情况下,List 将被升级为 List[Any]
)。
关于scala - 在具有协变类型的 Scala 参数化类中实现方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54163830/