我注意到不可变堆栈的ScalaDoc引用了一个前缀为以下签名的方法:
class Stack[A+] ...
def +: (elem: A): Stack[A]
该方法签名对我来说看起来不对,因为Stack在A类型参数中是协变的(因此elem的类型应该是编译器错误)。更重要的是,Scaladoc说这个方法的定义是在GenSeqLike中,但它似乎并不存在。
SeqLike有+的实现:我想象的是Stack正在使用的那个。
trait SeqLike[+A, +Repr] ...
def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
b += elem
b ++= thisCollection
b.result
}
这看起来不像Stack.push那样有效。
当我尝试提供我自己的+ :(作为push)的实现时,我确实得到了我所覆盖的方法不存在的预期编译器错误以及协方差问题。
class Stack2[+A] extends Stack[A] {
override def +: (elem: A): Stack[A] = this push elem
}
scalac Stack2.scala给出:
Stack2.scala:4: error: method +: overrides nothing
override def +: (elem: A): Stack[A] = this push elem
^
Stack2.scala:4: error: covariant type A occurs in contravariant position in type A of value elem
override def +: (elem: A): Stack[A] = this push elem
^
two errors found
是否可以实现+:有效使用push?
答案 0 :(得分:7)
这里的文档有点令人困惑。您会注意到该方法被标记为用例。实际的签名就是这个:
def +: [B >: A, That] (elem: B)(implicit bf: CanBuildFrom[Stack[A], B, That]): That
Prepends an element to this immutable stack
用例只显示了您可能使用它的典型方式(即使SeqLike
中的真实签名发生了变化,用例也没有从GenSeqLike
更改,因此显然不正确的归因)。
你是正确的+:
的实现效率不高,但鉴于您发布的代码,您无法确定这一点。 b ++= thisCollection
可以注意到其余部分只是一个堆栈并在前面推送elem
。但事实并非如此; b
只是引擎盖下的ArrayBuffer
。
所以请使用列表,就像文档建议的那样。