Как вы определяете локальный var / val в первичном конструкторе в Scala? - PullRequest
60 голосов
/ 13 июля 2009

В Scala первичный конструктор класса не имеет явного тела, но определяется неявно из тела класса. Как же тогда различать поля и локальные значения (то есть значения, локальные для метода конструктора)?

Например, возьмем следующий фрагмент кода, модифицированную форму некоторого примера кода из «Программирование в Scala»:

class R(n: Int, d: Int) {
   private val g = myfunc
   val x = n / g
   val y = d / g
}

Насколько я понимаю, это создаст класс с тремя полями: закрытое "g" и открытое "x" и "y". Однако значение g используется только для вычисления полей x и y и не имеет значения за пределами области конструктора.

Итак, как в этом (по общему признанию) искусственном примере определить локальные значения для этого конструктора?

Ответы [ 4 ]

37 голосов
/ 13 июля 2009

1001 * Е.Г. *

class R(n: Int, d: Int) {
  val (x, y) = {
    val g = myfunc
    (n/g, d/g)
  }
}
16 голосов
/ 13 июля 2009

Есть несколько способов сделать это. Вы можете объявить такие временные переменные в частных определениях, которые будут использоваться во время создания. Вы можете использовать временные переменные внутри блоков, которые возвращают выражения (например, в ответе Алаза). Или, наконец, вы можете использовать такие переменные внутри альтернативных конструкторов.

Подобно альтернативным конструкторам, вы также можете определить их в методе apply объекта-компаньона.

То, что вы не можете сделать, это объявить поле "временным".

Обратите внимание, что любой параметр, полученный первичным конструктором, также является полем. Если вы не хотите, чтобы такие параметры становились полями, и не хотите показывать действительные поля в конструкторе, обычное решение - сделать первичный конструктор частным с действительными полями и использовать либо альтернативный конструктор, либо apply () объекта-компаньона как эффективный «первичный» конструктор.

13 голосов
/ 28 января 2010

Другой вариант, который у нас есть, - сделать конструктор первичного объекта частным и использовать метод apply объекта-компаньона в качестве построителя. Если мы применим (каламбур не предназначен) этот подход к вашему примеру, он будет выглядеть так:

class R private (val x: Int, val y: Int);

object R {
  def apply(n: Int, d: Int): R = {
    val g = myfunc;
    new R(n / g, d / g);
  }
}

Чтобы создать экземпляр R вместо:

val r = new R(1, 2);

написать:

val r = R(1, 2);

Это немного многословно, но, я думаю, могло быть и хуже :). Будем надеяться, что частные [this] vals будут рассматриваться как временные переменные в будущих версиях Scala. Сам Мартин намекнул на это.

6 голосов
/ 14 июля 2009

Некоторые обсуждения на эту тему, включая комментарии Мартина Одерского, здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...