在Scala方差中,可以使用 +和 - 在通用类型参数上的方差运算符定义。例如 List 类型是标准库中的协变量。

class List[+A]

因此,可以这样定义具有协变量列表的函数:

def foo[A](list : List[A])

同样可以使用通用界限来模拟差异。所以我们也可以写这个

def foo[A](list : List[_:< A])

当然这是没有意义的,因为 list 已经协变了。但是,对于不协变量的类型可以做同样的技巧。 (像 Stack)。当然,也可以从协变量的堆栈(聚合的继承)创建一种新类型。

所以我的问题:

  1. 什么时候应该使用通用界限来进行方差?我们什么时候应该创建新的协变量类型?
  2. 通用界限仅对方差有用,或者他们可以声明更多(语言概念)。
  3. 如果它们仅对方差有用,则仅是与Java的兼容性?

提前thx :)

有帮助吗?

解决方案

如果类型自然是协变量或违反的,则应该这样声明。您的用户会感谢您。使用站点的差异确实是由于Java的。更确切地说是一种类型 Array[T <: Number] 被视为存在类型的速记:

ArrayBuffer[T] forSome { type T <: Number }

在Scala中,存在类型具有相当大的语法。这是有意的,因为我们不建议您使用它们太多。您什么时候需要存在类型?

  1. 用通配符编写Java类型的类似物,例如 List<? extends Number>.
  2. 写下Java Raw类型的类似物,例如 List.

在Java中,原始类型和通配符类型并不完全相同,也不与存在类型完全相同(即使我们知道它们不是什么,也很难确切地陈述它们是什么)。但是它们在实践中足够接近存在,因此Scala将它们映射到这种类型的情况下就摆脱了。

其他提示

  1. 在创建新的通用类型时,例如foo [t],您应该努力确定该类型是协方差,逆转或不变的,并分别声明它[+t],foo [-t]或foo [t]。诚然,这可能有点困难。但是,它每次使用通用界限都需要使用FOO时,可以释放FOO的用户。简而言之:当差异是类型本身的属性时,优先选择声明站点差异而不是呼叫站点差异。

顺便说一句,Martin Odersky,Lex Spoon和Bill Venners的Scala Book中的编程有一些关于差异的绝佳海带。请参阅第19章类型参数化。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top