Вопрос по scala, scala-primary-constructor – Как вы определяете локальный var / val в первичном конструкторе в Scala?

60

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

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

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

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

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

Публикация на случай, если у других возникнет такой же вопрос, как у меня, и они пришли сюда первыми, как я. Если вы пытаетесь сделать то же самое понятие, но дляconstructors используйте ответ на мой вопрос:stackoverflow.com/questions/46455835/… Oscar Godson

Ваш Ответ

4   ответа
11

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

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. Мартин сам намекал на это.

Начиная с Scala 2.9.0.RC1 оптимизация еще не реализована.
Робинст, даже в Scala 2.10.2
16

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

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

Что тыcan't do объявляет поле "временным".

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

Спасибо за разъяснения. skaffman
6
Тема удалена.
Это точный пример из книги, который вызвал мой вопрос :) Полагаю, это означает, что я обращал внимание ... skaffman
Альтернативная ссылка:scala-lang.org/node/1198#comment-3430
37

class R(n: Int, d: Int) {
  val (x, y) = {
    val g = myfunc
    (n/g, d/g)
  }
}
Я не вижу, как это ответ. Я вижу проблему сейчас в 2.10.0-RC5.
Это может быть важно. Спасибо за комментарий, Хорхе.
Это фактически добавит скрытое поле Tuple2 в ваш класс.
Ах, на самом деле просто. Я все еще чувствую свою интуицию в отношении функциональной концепции. skaffman

Похожие вопросы