Относительно:
val myList = List(1,2,3)
Когда компилятор встречает выражение, которое создает экземпляр класса без модификатора new
, он ищет этот объект-класс для поиска метода .apply
.В случае списка это определяется как:
override def apply[A](xs: A*): List[A] = xs.toList
Таким образом, это успешно компилируется.Вы можете увидеть это, когда попросите компилятор выдать информацию о типе после фазы typer:
def main(args: Array[String]): Unit = {
val l: List[Int] = scala.collection.immutable.List.apply[Int](1, 2, 3);
()
}
Будет ли myList ссылкой на isntance объекта List?
тип времени выполнения myList
будет либо минусом (::
), либо пустым списком (Nil
).
, если productElement является абстрактным методом, как это можно реализовать?
Это трюк с компилятором.productElement
и productArity
(и более) оба генерируются во время компиляции для любого определения класса наблюдения.Например, с учетом следующего класса дела:
case class Bar(i: Int)
Компилятор генерирует:
// an incomplete view of the generated case class methods and fields
// omitted for brevity.
case class Bar extends AnyRef with Product with Serializable {
<caseaccessor> <paramaccessor> private[this] val i: Int = _;
<stable> <caseaccessor> <accessor> <paramaccessor> def i: Int = Bar.this.i;
def <init>(i: Int): yuval.tests.Foo.Bar = {
Bar.super.<init>();
()
};
<synthetic> def copy(i: Int = i): yuval.tests.Foo.Bar = new Bar(i);
<synthetic> def copy$default$1: Int = Bar.this.i;
override <synthetic> def productPrefix: String = "Bar";
// this is the relevant part to your question
<synthetic> def productArity: Int = 1;
<synthetic> def productElement(x$1: Int): Any = x$1 match {
case 0 => Bar.this.i
case _ => throw new IndexOutOfBoundsException(x$1.toString())
};