Это ошибка, потому что это A[A[T]]
ковариантной в типе T.
Определение типа ковариантной от Wikipedia:
Within the type system of a programming language, a typing rule or a type constructor is:
- covariant if it preserves the ordering of types (≤), which orders types from more specific to more generic;
- contravariant if it reverses this ordering;
Рассмотрим следующий пример:
class Fruit
class Banana extends Fruit
и
Banana <: Fruit
A[Banana] :> A[Fruit] // Because A is contravariant in type T
A[A[Banana]] <: A[A[Fruit]] // Again because A is contravariant in type T
Последнее заявление означает, что A[A[T]]
является covariant, поскольку он сохраняет порядок типов от более конкретных до более общих.
Так что можно сделать:
scala> type AA[+T] = A[A[T]]
defined type alias AA
scala> type AAA[-T] = A[A[A[T]]]
defined type alias AAA
Но следующее приведет к ошибке:
scala> type AA[-T] = A[A[T]]
<console>:15: error: contravariant type T occurs in covariant position in type [-T]A[A[T]] of type AA
type AA[-T] = A[A[T]]
^
scala> type AAA[+T] = A[A[A[T]]]
<console>:15: error: covariant type T occurs in contravariant position in type [+T]A[A[A[T]]] of type AAA
type AAA[+T] = A[A[A[T]]]
^
И, наконец, возвращаясь к первоначальному вопросу есть одно и то же нарушение правила дисперсии в class B
поскольку базовый класс A[A[T]]
является ковариантным по типу T
по строительству.
Чтобы понять, почему это запрещено давайте предположим, что это возможно:
class B[-T] extends A[A[T]]
В этом случае мы получаем:
B[Fruit] <: B[Banana] <: A[A[Banana]]
так
val fruits: B[Fruit] = new B[Fruit]
val bananas1: B[Banana] = fruits
val bananas2: A[A[Banana]] = bananas1
Теперь мы имеем значение bananas2
типа A[A[Banana]]
, который указывает на экземпляр A[A[Fruit]]
, который нарушает безопасность типа с A[A[Banana]] <: A[A[Fruit]]
.
'' - это конструктор, и он определяется неявно. –
rightfold
Тогда почему я могу определить 'class B [-T]'? Также будет существовать метод 'init' и вернуть мне« B [T] », и он компилируется отлично. –