我知道当你输入:
val list = List(2,3)
您正在访问List对象的apply方法,该方法返回List。我无法理解的是,当List类是抽象的并且因此不能直接实例化时,为什么这是可能的(新的List()不会编译)? 我还想问一下有什么区别:
val arr = Array(4,5,6)
和
val arr = new Array(4, 5, 6)
答案 0 :(得分:7)
List
班级为sealed
和abstract
。它有两个concreate实现
Nil
代表一个空列表::[B]
表示带有头尾的非空列表。 ::[B]
in the documentation 当你致电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
,然后适当地设置元素。