+- Знаки в родовой декларации в Scala

Я искал документацию для PartialFunction по этой ссылке:

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

Может быть, кто-то может помочь прояснить значение знаков плюс и минус в общей декларации?

3 ответа

Решение

"+" и "-" означают ковариантный и контравариантный типы соответственно. Короче говоря, это означает, что:

PartialFunction[-A1, +B1] <: PartialFunction[-A2, +B2] только если A1 :> A2 а также B1 <: B2, где <: это подтип отношений.

"-" обычно применяется для входных параметров, "+" для вывода - в C# они даже используют соответствующие ключевые слова in а также out, В Java также есть более примитивная универсальная поддержка отклонений, построенная на экзистенциальных типах - на самом деле вы можете сделать это, используя _ <: SomeType (ковариация) или члены абстрактного типа type T <: SomeType в Скале тоже.

Без модификаторов PartialFunction[A1, B1] не будет иметь прямого отношения к PartialFunction[A2, B2] (другими словами, это будет инвариант).

PS Есть также некоторые ограничения, применяемые к таким типам, например, ковариантный ("+") тип не может находиться в контравариантной позиции (вы можете только вернуть его из метода) и наоборот. Это сделано для того, чтобы поддержать принцип подстановки Лискова и, естественно, понятным путем интерпретации "in" / "out".

Также стоит отметить, что A => B (синтаксис сахара для Function1) сам использует ко / противо-дисперсию:

 trait Function1 [-T1, +R] extends AnyRef

Это ковариация и контравариантность. 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:

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

Другие вопросы по тегам