В 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 и не имеет значения за пределами области конструктора.

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

60
skaffman 13 Июл 2009 в 14:17

4 ответа

Лучший ответ

Например.

class R(n: Int, d: Int) {
  val (x, y) = {
    val g = myfunc
    (n/g, d/g)
  }
}
37
Alexander Azarov 13 Июл 2009 в 11:39

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

6
Andrejs 12 Авг 2013 в 10:41

Другой вариант, который у нас есть, - сделать конструктор основного объекта закрытым и использовать в качестве конструктора метод 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] переменные будут рассматриваться как временные переменные в будущих выпусках Scala. Об этом намекнул сам Мартин.

13
Maxim Vladimirsky 29 Янв 2010 в 13:25

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

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

Что вы не можете сделать, так это объявить поле «временным».

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

16
Daniel C. Sobral 13 Июл 2009 в 12:19