0

我正在学习 Scala 的路上,我很难理解逆变、协变、不变性等。从为什么这个例子不能编译,也就是如何(co-, contra-, and in-)方差工作?我已经了解了如何将函数视为另一个函数的子类型。(知道真的很有用!)

下面的代码是我认为解决我的难题的重要部分。我已经提取了我认为会给问题增加不必要的复杂性的部分。根据示例,我有一个 Student 对象,它将充当工厂来生成函数。

函数将采用 AnyVal 的类型或子类型(Int、Double、Long 等),并且返回输出将具有相同的输入类型。为了实现这一点,学生类接受一个泛型 (A),它是 AnyVal 的子类型。抽象类在那里,因此我可以通过执行类似 List[Master[AnyVal]](Student.func1) 之类的操作来引用这些学生的列表。

问题是我不能有“val function: List[A] => A”这一行,因为我得到错误“协变类型 A 出现在类型 => List[A] => A 的值函数的逆变位置”。我不知道为什么返回类型必须是 A 的逆变器。对于基于 Function1 特征的名称,我在某种程度上可以接受这个事实。

那么我将如何在抽象 Master 类中定义我的函数,以便返回类型是 A 类型的逆变器?我找到了一个如何使用函数定义来定义它的示例(例如 def function[B >: A](v: B): List[B]),但是我将如何使用匿名函数来实现它呢?请记住,主抽象类中的“A”必须是协变的,因为会有一个函数列表接受所有 AnyVal 类型(Int、Double 等)

真的很感谢帮助!让我知道我的任何术语是否关闭。- 斯卡拉学习者

abstract class Master[+A] {
    val function: List[A] => A
}

class Student[A <: AnyVal](val function: List[A] => A) extends Master[A]

object Student {
def func1 =
    new Student((params: List[Int])=>params(0) + params(1))
}

val myFunc = Student.func1
val someList = List[Master[AnyVal]](myFunc)
4

1 回答 1

0

创建用协变类型参数化的泛型类或特征是非常困难的。一旦添加了方差注释,就不能将类型用作任何类方法的参数。这是因为函数的参数是逆变的,返回类型是协变的。在这个公认的答案中有一个很好的解释。

如果你真的希望类型是协变的,你必须编写所有的方法来接受 [B >: A] 类型的参数——也就是说,把 A 的超类型作为它们的参数类型。这可能非常具有挑战性;在线 Scala 文档有一个可能需要的杂技示例。

于 2013-09-08T11:25:39.300 回答