在带有协变类型的Scala参数化类内实现方法 [英] Implementing a method inside a Scala parameterized class with a covariant type
问题描述
我已经阅读了一些教程,其中包括有关协变类型的方法签名的主要Scala文档。假设我有以下抽象类:
I've read a few tutorials including the main Scala documentation regarding method signatures of covariant types. Suppose I have the following abstract class:
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的超类型。这可以解决什么问题?我正在尝试从直观的角度理解这一点。
My question concerns the signature of the add()
method. Why is it necessary to declare it that way? We are passing in a parameter that is a supertype of A. What problem does this solve? I'm trying to understand this on an intuitive level.
推荐答案
形式上的解释
给出
Formal explanation
Given
abstract class List[+A] {
def add(element: A): List[A]
}
该程序无法编译,因为
add
中的参数 element 的类型为A
,我们将其声明为协变。这不起作用,因为函数在其参数类型中为 contravariant ,而在其结果类型中为 covariant 。为此,我们需要在add
中翻转参数 element 类型的方差。
为此,我们引入了一个新的类型参数B
,该参数具有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.
直观的解释
在此示例中,如果您添加
到列表中:
必须为 A
-在这种情况下列表仍然是列表[A]
。
或者它必须是任何子类型 A
-在这种情况下,元素被上载到 A
,而 List 仍然是 List [A]
。
还是其他类型的 B
,则它必须是 A
的超类型-在这种情况下,列表被向上链接为列表[B]
。 (注意:由于任何
只是所有内容的超类,在最坏的情况下,列表将被投射为列出[任何]
)。
Intuitive explanation
In this example, if you add
something to a List:
It must be an A
- in this case the List is still a List[A]
.
Or it must be any subtype of A
- in this case the element gets upcasted to A
, and the List remains a List[A]
.
Or if it is another type B
, then it MUST be a supertype of A
- in this case the List gets upcasted to a List[B]
. (Note: Because Any
is just a supertype of everything, in the worst case the List will be upcasted to List[Any]
).
这篇关于在带有协变类型的Scala参数化类内实现方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!