override def prependedAll[B >: A](prefix: collection.IterableOnce[B]): List[B] = prefix match {
case xs: List[B] => xs ::: this
case _ if prefix.knownSize == 0 => this
case b: ListBuffer[B] if this.isEmpty => b.toList
case _ =>
val iter = prefix.iterator
if (iter.hasNext) {
val result = new ::[B](iter.next(), this)
var curr = result
while (iter.hasNext) {
val temp = new ::[B](iter.next(), this)
curr.next = temp
curr = temp
}
releaseFence()
result
} else {
this
}
}
3条答案
按热度按时间ct2axkht1#
Seq
是一个特征,List
是一个(默认)实现。https://github.com/scala/scala/blob/v2.13.10/src/library/scala/collection/immutable/Seq.scala#L39
Seq
是一个特性,无法初始化特性首先,即使
X
是一个trait,您也可以示例化一个扩展trait的匿名类:new X {}
。(顺便说一下,List
也是一个抽象类。)其次,
Seq[Int]()
被去糖化为Seq.apply[Int]()
,你引用的不是traitSeq
,而是它的伴随对象。ryoqjall2#
您从
Seq
伴随对象调用了apply
。apply
的实现返回了List[Int]
,它是Seq[Int]
的示例5vf7fwbs3#
没有魔法。
这里有一些简单的代码,大致如下所示:
换句话说,
Seq.apply
会委派给List.apply
,因此当您呼叫Seq(1, 2, 3)
时,它会委派给List(1, 2, 3)
,而List(1, 2, 3)
会传回List
。Here is an extremely simplified runnable Scastie demonstration:
真实的的代码当然要比这个简单的例子更一般和抽象,
Seq
对象本身没有apply
方法,而是继承自SeqFactory.Delegate[Seq](List)
:而
SeqFactory.Delegate[Seq](List)
的apply
方法则会委派给对象的apply
方法,该对象是以delegate
参数传递的:如果你还记得的话,
delegate
参数是List
object:List
没有自己的apply
方法,而是从IterableFactory
继承,如下所示:因此,它只是委托给
from
,这是一个抽象方法,它是这样实现的:因此,
from
会委派给Nil.prependedAll
。Nil
会从List
继承prependedAll
,其外观如下所示:在本例中,您要构造一个空的
Seq
,您将遇到第二种情况:它只返回
this
,即Nil
,它是List[A]
的一个示例。因此,Seq[Int]()
的 * 运行时类 * 是List[Int]
,但当然,* 静态类型 * 仍然是Seq[Int]
。最常见的情况是第四种情况,它获取
prefix
的iterator
,然后在while
循环中循环iterator
。注意:这 * 不是 *“Scala方式”!Scala标准库为了性能和/或平台互操作性而采取了一些捷径,和/或仅仅是因为在库中的这个特定点,我们所习惯的高级抽象不可用,因为首先提供这些抽象的是标准库。Scala的方法是fold,就像我上面做的那样。
因此,尽管真实的的Scala库要经过六个额外的间接层,但它与我上面编写的简化代码片段非常等效。