4

我知道当您键入时:

val list = List(2,3)

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

val arr = Array(4,5,6)

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

2 回答 2

7

Listsealedabstract。它有两个concreate实现

  1. Nil代表一个空列表
  2. ::[B]它表示一个带头和尾的非空列表。::[B]在文档中

当您调用List.apply它时,它会跳过一些环节并为您提供::[B]案例类的实例。

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

于 2013-02-25T11:33:43.730 回答
6

我开始写,确定这一点的简单方法是查看您正在调用的方法的来源,这些方法可从ScalaDoc 获得。但是,实际构建列表所经历的各种间接级别都掩盖了“简单”一词!如果您愿意,值得一看,从定义如下apply的对象中的方法开始:List

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

您可能知道也可能不知道表单的参数在xs : A*内部被视为 a Seq,这意味着我们正在调用toLista 上的方法,该方法SeqTraversableOnce. 然后,这委托给一个泛型方法,该方法查找实际构造列表to的隐式方法 。CanBuildFrom所以你得到的是一些ListCanBuildFrom. 你实际得到的是 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然后适当地设置元素。

于 2013-02-25T11:37:13.840 回答