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
}
Что рекомендуется и почему?
Ответы
Ответ 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
}