Scala中List(),Array()和新List(),新Array()之间的差异

时间:2013-02-25 11:20:34

标签: scala

我知道当你输入:

val list = List(2,3)

您正在访问List对象的apply方法,该方法返回List。我无法理解的是,当List类是抽象的并且因此不能直接实例化时,为什么这是可能的(新的List()不会编译)? 我还想问一下有什么区别:

val arr = Array(4,5,6)

val arr = new Array(4, 5, 6)

2 个答案:

答案 0 :(得分:7)

List班级为sealedabstract。它有两个concreate实现

  1. Nil代表一个空列表
  2. ::[B]表示带有头尾的非空列表。 ::[B] in the documentation
  3. 当你致电List.apply时,它会跳过一些箍,为你提供一个::[B]案例类的实例。

    关于数组:new Array(4, 5, 6)将抛出编译错误,因为数组的构造函数定义如下:new Array(_length: Int)apply伴随对象的Array方法使用参数创建Array的新实例(在ArrayBuilder的帮助下)。

答案 1 :(得分:6)

我开始写道,确定这个问题的简单方法是查看您正在调用的方法的来源,这些来源可以从ScalaDoc获得。然而,实际建立一个列表所经历的各种间接层面都是“容易”这个词!值得一看,如果你想要的话,从apply对象中的List方法开始,定义如下:

override def apply[A](xs: A*): List[A] = xs.toList

您可能知道或不知道xs : A*形式的参数在内部被视为Seq,这意味着我们在{{1}上调用toList方法},在Seq中定义。然后,它委托一个通用的TraversableOnce方法,该方法寻找一个隐式的方法 实际构建列表的to。所以你得到的是由CanBuildFrom选择的List的一些实现。你实际得到的是一个CanBuildFrom,它实现了一个单链表。

幸运的是,scala.collection.immutable.$colon$colon的行为更容易查找:

Array.apply

因此, def apply[T: ClassTag](xs: T*): Array[T] = { val array = new Array[T](xs.length) var i = 0 for (x <- xs.iterator) { array(i) = x; i += 1 } array } 只委派给Array.apply,然后适当地设置元素。