Вот некоторый код из this урока:Почему входные параметры контравариантны в методах?
case class ListNode[+T](h: T, t: ListNode[T]) {
def head: T = h
def tail: ListNode[T] = t
def prepend(elem: T): ListNode[T] =
ListNode(elem, this)
}
В учебнике говорится:
К сожалению, эта программа не компилируется, так как ковариация аннотаций возможно только, если тип переменной только в используется ковариантные позиции. Поскольку переменная типа T появляется как тип параметра метода prepend, это правило нарушается.
Как T
не в ковариантной позиции в predend
и другие T
ссылки (def head: T = h
и def tail: ListNode[T] = t
), по-видимому, ковариантны?
Что я спрашиваю, почему T
в prepend
не ковариант. Это, конечно, не описано в Why is Function[-A1,...,+B] not about allowing any supertypes as parameters?, что, как мне кажется, было направлено другими.
Это как написано. В двух других методах 'T' находится в контравариантном положении, это _only_ в возвращаемом типе, тогда как для' preend' он также находится в параметре ('elem: T'), поэтому он может быть только инвариантным. –
Рассмотрим следующий пример: 'trait Fruit; класс Apple расширяет Fruit; класс Груша расширяет Фрукты. Предположим, что 'ListNode' является ковариантным, поэтому' ListNode [Apple] 'также является' ListNode [Fruit] ':' val node: ListNode [Fruit] = ListNode [Apple] (новый Apple(), null) '. Теперь, если вы 'prepend' с другим' Fruit', 'node.prepend (new Pear())', вы явно не получите (typeafe) 'ListNode [Apple]'. –