Scala官方文档Variances示例代码

时间:2015-06-18 16:19:46

标签: scala

http://docs.scala-lang.org/tutorials/tour/variances.html上有示例代码

scala> class Stack[+A] {
 |   def push[B >: A](elem: B): Stack[B] = new Stack[B] {
 |     override def top: B = elem
 |     override def pop: Stack[B] = Stack.this
 |     override def toString() = elem.toString() + " " + Stack.this.toString()
 |   }
 |   def top: A = sys.error("no element on stack")
 |   def pop: Stack[A] = sys.error("no element on stack")
 |   override def toString() = ""
 | }

然后我定义了两个类BC

scala> class B(val d: Int)
scala> class C(override val d: Int) extends B(d)

我分别实例化o1o2类型的对象BC并将它们推入堆栈

scala> val o1 = new B(1)
o1: B = B@17046283

scala> val o2 = new C(2)
o2: C = C@2c767a52

scala> var s: Stack[B] = new Stack().push(o1)
s: Stack[B] = B@17046283

scala> s.top
res1: B = B@17046283

scala> s = s.push(o2)
s: Stack[B] = C@2c767a52 B@17046283

scala> s = s.pop
s: Stack[B] = B@17046283

scala> var s: Stack[B] = new Stack().push(o1)
s: Stack[B] = B@17046283

scala> s = s.push(o2)
s: Stack[B] = C@2c767a52 B@17046283

scala> s = s.push(o1)
s: Stack[B] = B@17046283 C@2c767a52 B@17046283

我的问题是为什么s的所有返回类型都是Stack[B]。从代码中可以看出Stack[C]调用可以返回push吗?对不起,我是新手。

2 个答案:

答案 0 :(得分:0)

B >: A表示BA超类型(包括A)

实际上,这意味着当你有一个Stack[B]并尝试push某种类型A时,编译器会尝试找到它之间最具体的常见超类型。 2。

由于CB子类型,因此C和B之间最常见的超类型为B

答案 1 :(得分:0)

A是协变的,因此Stack[C]Stack[B]的子类型,因为CB的子类型。 push的签名意味着如果您推送A的超类型,则会收到Stack[Supertype]。这意味着将B推送到Stack[C]将返回Stack[B]

val s = Stack[C]()
val bs: Stack[B] = s.push(new B(1))

但是,您开始使用Stack[B],因此推送C将不会返回Stack[C],因为堆栈可能包含B的实例。您可以推送B的超类型:

val as: Stack[Any] = s.push(1)