Я смотрел документацию для PartialFunction в эту ссылку:
trait PartialFunction[-A, +B] extends (A) ⇒ B
Может кто-то может помочь прояснить значение знаков плюс и минус в общей декларации?
Я смотрел документацию для PartialFunction в эту ссылку:
trait PartialFunction[-A, +B] extends (A) ⇒ B
Может кто-то может помочь прояснить значение знаков плюс и минус в общей декларации?
"+" и "-" означают ковариантные и контравариантные типы соответственно. Короче говоря, это означает, что:
PartialFunction[-A1, +B1]
<: PartialFunction[-A2, +B2]
, только если A1 :> A2
и B1 <: B2
, где <:
- отношение подтипирования.
"-" обычно применяется для входных параметров, "+" для вывода - на С# они даже используют соответствующие ключевые слова in
и out
. Существует также более примитивная общая поддержка дисперсии в Java, построенная на экзистенциальных типах - на самом деле вы можете сделать это, используя _ <: SomeType
(ковариация) или абстрактные члены типа type T <: SomeType
в Scala.
Без модификаторов PartialFunction[A1, B1]
не будет иметь прямого отношения к PartialFunction[A2, B2]
(другими словами, он будет инвариантным).
P.S. Существуют также некоторые ограничения, применяемые к таким типам, такие как ковариантный ( "+" ) тип не могут находиться в контравариантном положении (вы можете вернуть его только из метода) и наоборот. Это делается для поддержки Принципа замены Лискова и, естественно, понятно из-за интерпретации "in" / "out".
Кроме того, стоит заметить, что A => B
(синтаксический сахар для Function1
) сам использует co-/contra-variance:
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: