Значение поля, сгенерированное классом случая Scala

У меня есть существующее приложение Scala, и оно использует классы case, которые затем сохраняются в MongoDB. Мне нужно ввести новое поле в класс case, но его значение получено из существующего поля.

Например, есть номер телефона, и я хочу добавить нормализованный номер телефона, сохранив исходный номер телефона. Я обновлю существующие записи в MongoDB, но мне нужно будет добавить эту функцию нормализации в существующий код сохранения и обновления.

Итак, есть ли в Scala какой-нибудь удобный ярлык для добавления «крючка» к определенному полю класса case? Например, в Java можно изменить установщик номера телефона.

Редактировать:

Решение в ответе Кристиана отлично работает само по себе, но в моем случае у меня есть значения по умолчанию для полей (я думаю, из-за Салата...)

case class Person(name: String = "a", phone: Option[String] = None, normalizedPhone: Option[String] = None)

object Person {
  def apply(name: String, phone: Option[String]): Person = Person(name, phone, Some("xxx" + phone.getOrElse("")))
}

А если использовать что-то вроде: Person(phone = Some("s"))

Я возьму: Person = Person(a,Some(s),None)


person Petteri H    schedule 13.06.2014    source источник


Ответы (3)


Вы можете определить метод применения в сопутствующем объекте:

case class Person(name: String, phone: String, normalizedPhone: String)

object Person {
  def apply(name: String, phone: String): Person =  Person(name, phone, "xxx" + phone)
}

Затем в ответе:

scala> Person("name", "phone")
res3: Person = Person(name,phone,xxxphone)
person Christian    schedule 13.06.2014
comment
Это отвечает на мой первоначальный вопрос. В итоге я выбрал совершенно другое решение, нормализовав поле на месте и вообще не вводя новое. - person Petteri H; 17.06.2014

Вы можете добавить в класс case методы, которые будут содержать логику преобразования из существующих полей. Например:

case class Person(name: String, phone: String) {
  def normalizedPhone = "+40" + phone
}

Затем вы можете использовать метод так же, как если бы это было поле:

val p1 = new Person("Joe", "7234")
println(p1.normalizedPhone) // +407234
person dzs    schedule 13.06.2014
comment
В моем случае я думаю, что мне нужно иметь его как отдельное поле, чтобы сохранить его в MongoDB. - person Petteri H; 13.06.2014
comment
Но зачем сохранять его, если он всегда получен из другого поля? Не будет ли это избыточностью? - person dzs; 13.06.2014
comment
Он должен быть в БД, чтобы индексировать его и быстро запрашивать. Запрос регулярного выражения MongoDB был недостаточно быстрым. - person Petteri H; 13.06.2014

Я думаю, что это близко к тому, что вам нужно. Поскольку вы не можете переопределить сгенерированный мутатор, добавьте к существующему полю префикс подчеркивания, сделайте его закрытым, а затем напишите методы доступа и мутатора для исходного имени поля. После этого вам потребуется только дополнительная строка в конструкторе для инициализации поля на основе конструктора.

case class Test(private var _phoneNumber: String, var formatted: String = "") {
  phoneNumber_=(_phoneNumber)

  def phoneNumber = _phoneNumber

  def phoneNumber_=(phoneNumber: String) {
    _phoneNumber = phoneNumber
    formatted = "formatted" + phoneNumber
  }
}

object Test {
  def main(args: Array[String]) {
    var t = Test("09048751234")

    println(t.phoneNumber)
    println(t.formatted)

    t.phoneNumber = "08068745963"

    println(t.phoneNumber)
    println(t.formatted)
  }
}
person Robby Cornelissen    schedule 13.06.2014