在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() = ""
| }
然后我定义了两个类B
和C
scala> class B(val d: Int)
scala> class C(override val d: Int) extends B(d)
我分别实例化o1
和o2
类型的对象B
和C
并将它们推入堆栈
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
吗?对不起,我是新手。
答案 0 :(得分:0)
B >: A
表示B
是A
的超类型(包括A)
实际上,这意味着当你有一个Stack[B]
并尝试push
某种类型A
时,编译器会尝试找到它之间最具体的常见超类型。 2。
由于C
是B
的子类型,因此C和B之间最常见的超类型为B
。
答案 1 :(得分:0)
A
是协变的,因此Stack[C]
是Stack[B]
的子类型,因为C
是B
的子类型。 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)