在带有协变类型的Scala参数化类内实现方法 [英] Implementing a method inside a Scala parameterized class with a covariant type

查看:72
本文介绍了在带有协变类型的Scala参数化类内实现方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了一些教程,其中包括有关协变类型的方法签名的主要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 type A, 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 in add.
We do this by introducing a new type parameter B that has A 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆