Вы не можете написать def append(x: Sequence[A]): Sequence[A]}
, так как A находится в контравариантной позиции в аргументе append
, будучи одновременно ковариантным.
Вы должны написать это так:
abstract class Sequence[+A] {
def append[B >: A](x: Sequence[B]): Sequence[B]
}
У вас есть отличное объяснение в Почему пример не компилируется, иначе как (со-, противо- и не-) дисперсия работает?
Короче говоря:
+ A заявляет, что безопасно преобразовать этот A в супертип A во всех контекстах (собака может быть преобразована в животное). Если вы пишете append[A](x: Sequence[A])
, вы утверждаете, что x может быть только A или подтипами A (Dog, Yorsay и т. Д.), Но никогда не быть супертипом (например, Animal), поэтому это противоречит аннотации + A и завершается неудачно во время компиляции. С помощью сигнатуры append[B >: A](x: Sequence[B])
вы исправляете это, избегая именования A в аргументах функции.
Итак, [B >: A]
определяет нижнюю границу для B, заявляя, что B должен быть супертипом A или A, но никогда не являясь классом ниже A в иерархии, и, следовательно, соответствует сигнатуре + A.
Я знаю, что ковариация и контравариантность являются сложными понятиями и их трудно понять, я также время от времени путаюсь.