+- Scala 中的通用声明中的符号

Posted

技术标签:

【中文标题】+- Scala 中的通用声明中的符号【英文标题】:+- Signs in Generic Declaration in Scala 【发布时间】:2014-12-23 20:49:13 【问题描述】:

我正在查看 this link 中的 PartialFunction 文档:

trait PartialFunction[-A, +B] extends (A) ⇒ B

也许有人可以帮助澄清泛型声明中加号和减号的意义?

【问题讨论】:

【参考方案1】:

“+”和“-”分别表示covariant and contravariant 类型。简而言之,就是:

PartialFunction[-A1, +B1] <:>PartialFunction[-A2, +B2] 仅当A1 :&gt; A2B1 &lt;: B2,其中&lt;: 是子类型关系。

“-”通常用于输入参数,“+”用于输出 - 在 C# 中,它们甚至使用各自的关键字 inout。还有一些更原始的generic variance support in Java 建立在存在类型之上——实际上你也可以在Scala 中使用_ &lt;: SomeType(协方差)或抽象类型成员type T &lt;: SomeType

如果没有修饰符 PartialFunction[A1, B1] 将与 PartialFunction[A2, B2] 没有直接关系(换句话说,它将是不变的)。

附:这些类型也有一些限制,例如 covariant("+") 类型不能处于逆变位置(您只能从方法中返回它),反之亦然。这样做是为了支持Liskov Substitution Principle 并且自然可以通过“in”/“out”解释来理解。

另外,值得注意的是A =&gt; BFunction1 的语法糖)本身正在使用 co-/contra-variance:

 trait Function1 [-T1, +R] extends AnyRef

因为这些函数可以通过子类型进行扩展,这使得它们在理论上也是局部的(尽管 Scala 不是这样处理这些函数的)——即使从技术上讲,Scala 中的“全部”FunctionN 也可以扩展、重新定义、返回 null 等等。

【讨论】:

【参考方案2】:

这是协变和逆变。 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]

【讨论】:

【参考方案3】:

为了补充其他答案,这里是 scala-lang 网站上差异文档的链接:

https://docs.scala-lang.org/tour/variances.html

【讨论】:

以上是关于+- Scala 中的通用声明中的符号的主要内容,如果未能解决你的问题,请参考以下文章

Scala中的通用递归类型

通用优先级队列中的协变和逆变类型

在 Scala 中是不是有一种通用的方式来记忆?

scala中的=>符号的含义

为项目/工作区中的所有 Xcode 目标声明一个通用 Xcode 变量以在 plist 中使用

Go 语言中的通用类型(int / uint)相对于特定类型(int64 / uint64)有啥优势?