Экземпляр абстрактного класса Scala - PullRequest
0 голосов
/ 24 июня 2018

Я новичок в Скале. У меня вопрос по поводу List class. Это абстрактный и закрытый класс. Это означает, что его нельзя ни создать, ни расширить. Так каково его использование? Как это может быть, что-то вроде следующего работает?

val myList = List(1,2,3)

Будет ли myList ссылкой на isntance объекта List? Кроме того, если productElement является абстрактным методом, как это можно реализовать?

спасибо.

Ответы [ 2 ]

0 голосов
/ 24 июня 2018

Относительно:

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())
  };
0 голосов
/ 24 июня 2018

sealed означает, что его нельзя расширить за пределы файла, в котором он определен. Список равен sealed, но у него есть 2 неабстрактных подкласса, определенных в одном и том же файле: Nil и ::, представляющих пустой список и непустой список соответственно.

Когда вы звоните List(1,2,3), вы на самом деле не создаете экземпляр класса List напрямую. Это синтаксический сахар для List.apply(1, 2, 3), вызывающий метод apply объекта List (сопутствующий классу List). И этот метод (технически через некоторую косвенность) в конечном итоге создает экземпляр либо Nil, либо ::.

Вы можете увидеть список подклассов здесь: https://github.com/scala/scala/blob/2.13.x/src/library/scala/collection/immutable/List.scala#L547 https://github.com/scala/scala/blob/2.13.x/src/library/scala/collection/immutable/List.scala#L554

Вам не нужно реализовывать productElement, он создается компилятором scala для всех классов case.

...