【发布时间】:2014-12-23 20:49:13
【问题描述】:
我正在查看 this link 中的 PartialFunction 文档:
trait PartialFunction[-A, +B] extends (A) ⇒ B
也许有人可以帮助澄清泛型声明中加号和减号的意义?
【问题讨论】:
我正在查看 this link 中的 PartialFunction 文档:
trait PartialFunction[-A, +B] extends (A) ⇒ B
也许有人可以帮助澄清泛型声明中加号和减号的意义?
【问题讨论】:
“+”和“-”分别表示covariant and contravariant 类型。简而言之,就是:
PartialFunction[-A1, +B1] <:>PartialFunction[-A2, +B2] 仅当A1 :> A2 和B1 <: B2,其中<: 是子类型关系。
“-”通常用于输入参数,“+”用于输出 - 在 C# 中,它们甚至使用各自的关键字 in 和 out。还有一些更原始的generic variance support in Java 建立在存在类型之上——实际上你也可以在Scala 中使用_ <: SomeType(协方差)或抽象类型成员type T <: SomeType。
如果没有修饰符 PartialFunction[A1, B1] 将与 PartialFunction[A2, B2] 没有直接关系(换句话说,它将是不变的)。
附:这些类型也有一些限制,例如 covariant("+") 类型不能处于逆变位置(您只能从方法中返回它),反之亦然。这样做是为了支持Liskov Substitution Principle 并且自然可以通过“in”/“out”解释来理解。
另外,值得注意的是A => B(Function1 的语法糖)本身正在使用 co-/contra-variance:
trait Function1 [-T1, +R] extends AnyRef
因为这些函数可以通过子类型进行扩展,这使得它们在理论上也是局部的(尽管 Scala 不是这样处理这些函数的)——即使从技术上讲,Scala 中的“全部”FunctionN 也可以扩展、重新定义、返回 null 等等。
【讨论】:
这是协变和逆变。 https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
基本上它说明了泛型类型的继承将如何工作。
来自 Scala 的简单示例是 - trait Seq[+A]
因为 + ,所以代码
val s: Seq[Person] = Seq[Student]()
将编译,因为 Student 扩展了 Person。没有 + 它将无法工作
更复杂一点的示例 -
class C[-A, +B] {
def foo(param: A): B = ???
}
class Person(val name: String)
class Student(name: String, val university: String) extends Person(name)
val sample: C[Student, Person] = new C[Person, Student]
【讨论】:
为了补充其他答案,这里是 scala-lang 网站上差异文档的链接:
【讨论】: