我知道当您键入时:
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,这意味着我们正在调用toLista 上的方法,该方法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然后适当地设置元素。