考虑以下层次结构:
class Foo
class Bar extends Foo { def bar = () }
class Baz extends Bar { def baz = () }
还有一个类似于你的课程:
class Cov[+T](val item: T, val existing: List[T] = Nil) {
def append[S >: T](value: S) = new Cov[S](value, item :: existing)
}
然后我们可以为每个Foo
子类型构造三个实例:
val cFoo = new Cov(new Foo)
val cBar = new Cov(new Bar)
val cBaz = new Cov(new Baz)
还有一个需要bar
元素的测试功能:
def test(c: Cov[Bar]) = c.item.bar
它拥有:
test(cFoo) // not possible (otherwise `bar` would produce a problem)
test(cBaz) // ok, since T covariant, Baz <: Bar --> Cov[Baz] <: Cov[Bar]; Baz has bar
现在append
方法,回到上限:
val cFoo2 = cBar.append(new Foo)
这没关系,因为Foo >: Bar
, List[Foo] >: List[Bar]
, Cov[Foo] >: Cov[Bar]
.
现在,您的bar
访问权限已经正确:
cFoo2.item.bar // bar is not a member of Foo
要了解为什么需要上限,请想象以下可能
class Cov[+T](val item: T, val existing: List[T] = Nil) {
def append(value: T) = new Cov[T](value, item :: existing)
}
class BarCov extends Cov[Bar](new Bar) {
override def append(value: Bar) = {
value.bar // !
super.append(value)
}
}
然后你可以写
def test2[T](cov: Cov[T], elem: T): Cov[T] = cov.append(elem)
并且允许以下非法行为:
test2[Foo](new BarCov, new Foo) // BarCov <: Cov[Foo]
wherevalue.bar
将在 a 上调用Foo
。使用(正确)上限,您将无法append
像假设的最后一个示例中那样实现:
class BarCov extends Cov[Bar](new Bar) {
override def append[S >: Bar](value: S) = {
value.bar // error: value bar is not a member of type parameter S
super.append(value)
}
}
所以类型系统仍然是健全的。