我知道当您键入时:
val list = List(2,3)
您正在访问返回 List 的 List 对象的 apply 方法。我无法理解的是,为什么当 List 类是抽象类因此不能直接实例化(new List() 不会编译)时这可能?我还想问一下有什么区别:
val arr = Array(4,5,6)
和
val arr = new Array(4, 5, 6)
我知道当您键入时:
val list = List(2,3)
您正在访问返回 List 的 List 对象的 apply 方法。我无法理解的是,为什么当 List 类是抽象类因此不能直接实例化(new List() 不会编译)时这可能?我还想问一下有什么区别:
val arr = Array(4,5,6)
和
val arr = new Array(4, 5, 6)
类List
是sealed
和abstract
。它有两个concreate实现
Nil
代表一个空列表::[B]
它表示一个带头和尾的非空列表。::[B]
在文档中当您调用List.apply
它时,它会跳过一些环节并为您提供::[B]
案例类的实例。
关于数组:new Array(4, 5, 6)
会抛出编译错误,因为数组的构造函数是这样定义的:new Array(_length: Int)
。伴随对象的apply
方法Array
使用参数来创建一个新的实例Array
(在 的帮助下ArrayBuilder
)。
我开始写,确定这一点的简单方法是查看您正在调用的方法的来源,这些方法可从ScalaDoc 获得。但是,实际构建列表所经历的各种间接级别都掩盖了“简单”一词!如果您愿意,值得一看,从定义如下apply
的对象中的方法开始:List
override def apply[A](xs: A*): List[A] = xs.toList
您可能知道也可能不知道表单的参数在xs : A*
内部被视为 a Seq
,这意味着我们正在调用toList
a 上的方法,该方法Seq
在TraversableOnce
. 然后,这委托给一个泛型方法,该方法查找实际构造列表to
的隐式方法
。CanBuildFrom
所以你得到的是一些List
由CanBuildFrom
. 你实际得到的是 a 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
只需委托给new Array
然后适当地设置元素。