scala - 在具有协变类型的 Scala 参数化类中实现方法

标签 scala generics covariance contravariance

我已经阅读了一些教程,包括有关协变类型方法签名的主要 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 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.

直观的解释

在这个例子中,如果你添加一些东西到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/

相关文章:

scala - 如何在 Scala-IDE 中解析对旋转生成的模板类的引用?

json - Spark.RDD take(n) 返回元素为 n 的数组,n 次

c# - 将 IFoo<T> 转换为 IFoo<object> 的一般方法

scala - 我在哪里可以找到用 Scala 编写的纯函数式开源项目?

Delphi:泛型后代的泛型列表并以泛型作为参数

java - 如何保证泛型类型的类型

c# - 从 C# 通用字典中过滤掉值

c# - Autofac:使用 in 和 out 类型参数解析变体类型

sql - 使用 SQL 求协方差

java - Scala 导入和包错误