类型上界限制了一个类型是另外一个类型的子类型,而类型下界则声明了一个类型是另外一个类型的父类型。B >: A
表明了类型参数B
或者抽象类型B
是类型A
的超类。在大多数场景中,A
是作为类的类型参数,而B
会作为方法的类型参数。
1 | trait Node[+B] { |
这个程序实现了一个单向链表。Nil
表示一个空的元素(比如一个空的列表)。class ListNode
是一个Node
,它包含了一个类型B
的元素(head
)和一个列表中其余元素的引用(tail
)。class Node
和它的子类型是协变的,因为这里有+B
。
然而,这个程序不能通过编译,因为prepend
方法中的参数elem
是B
类型的,且声明了为协变的。这之所以行不通,是在于函数在它们的参数类型上是逆变的,而在它们的返回类型上是协变的。
为了解决这个问题,我们需要转变prepend
方法中参数类型的型变。我们可以引用新的类型U
,它的类型下界是B
,从而实现这一转变。
1 | trait Node[+B] { |
现在我们便可以像下面这样操作了:
1 | trait Bird |
Node[Bird]
被分配到africanSwallowList
,但是仍然可以接受EuropeanSwallow
。