Подтвердить что ты не робот

Scala передовая практика переменных экземпляра

Как перевести следующий код Java на Scala?

class ClassA {
    private int field1;
    private int field2;

    public ClassA() {
        field1 = 1;
        field2 = 2;
    }
}

Я вижу два варианта:

class ClassA(val field1: Int, val field2: Int) {
   ....
}

или

class ClassA {
   val field1: Int = 1
   val field2: Int = 2
}

Что рекомендуется и почему?

4b9b3361

Ответ 1

Нет простого перевода с Java на Scala, это зависит от контекста:

  • Являются ли переменные изменяемыми в Java? Если да (иначе они должны быть окончательными в Java): Имеет ли смысл сделать их неизменяемыми в Scala?
  • Должен ли конструктор оставаться открытым в Scala? Будет factory (например, применить метод в объект-компаньон) более подходящий?
  • Почему переменные являются частными? У них есть геттеры и/или сеттеры?
  • Когда нужны переменные, было бы разумно сделать их ленивыми?
  • Если значения неизменяемы и отображаются, будут ли они полезны при сопоставлении шаблонов? Будет ли класс case правильным выбором?
  • Могут ли переменные быть сгруппированы (например, в кортеже), чтобы упростить API и получить доступ?

Понимаете, так много соображений. Я бы посоветовал узнать о возможностях Scala и поиграть с разными подходами, иначе вы застряли в ловушке Scala как лучше Java "дольше, чем нужно.

Ответ 2

Это самый прямой перевод на Scala:

class ClassA{
  private var field1 = 1
  private var field2 = 2
}

Обратите внимание на использование var вместо val. val - неизменяемое поле, соответствующее public final в Java. Таким образом, это не может быть изменено позже, и предоставление возможности инициализации такого поля для правильного значения для данного экземпляра имеет важное значение.

Чтобы решить, что вы хотите использовать, вы должны задать себе вопросы, перечисленные в ответе Landei.

Ответ 3

Самое большое различие между ними состоит в том, что параметр класса можно использовать как конструктор. Если вы хотите, чтобы у конструктора не было никаких параметров, как ваш пример Java, вам нужно использовать второй, плюс добавление частного модификатора, как это предлагает @Debilski.

Другой вариант - использовать параметры по умолчанию в конструкторе. Таким образом, при необходимости поля могут быть изменены:

class ClassA (private val field1: Int = 1, private val field2: Int = 2)

// Using defaults
val a = new ClassA

// Setting new values
val b = new ClassA(3, 4)

Ответ 4

Если вы хотите иметь частные поля, почему бы не объявить их частными?

class ClassA {
  private val field1: Int = 1
  private val field2: Int = 2
}

Ответ 5

Если вы всегда хотите, чтобы это поле1 и поле2 имели одинаковое значение для каждого экземпляра класса A, я бы предложил разместить их в сопутствующем модуле:

object A {
  private val field1 = 1
  private val field2 = 2
}

И затем используйте их в классе A:

class A {
  def complexInternalComputation = 2*A.a
}

или следующим образом:

class A {
  import A._
  def complexInternalComputation = 2*a
}