Scala: Копирование классов классов с признаком
Я новичок в Scala, и у меня есть вопрос о наилучшем способе копирования класса case при сохранении данных, которые поступают из свойств. Например, допустим, что у меня есть следующее:
trait Auditing {
var createTime: Timestamp = new Timestamp(System.currentTimeMillis)
}
case class User(val userName: String, val email: String) extends Auditing
val user = User("Joe", "[email protected]")
Затем я хочу создать новую копию с одним измененным параметром:
val user2 = user.copy(email = "[email protected]")
Теперь, в приведенном выше примере, свойство createTime не копируется, потому что оно не определено в конструкторе класса case пользователя. Поэтому мой вопрос: если предположить, что перемещение createTime в конструктор не является опцией, каков наилучший способ для получения копии объекта User, который включает в себя значение из признака?
Я использую Scala 2.9.1
Спасибо заранее!
Джо
Ответы
Ответ 1
Вы можете переопределить метод копирования с этим поведением.
case class User(val userName: String, val email: String) extends Auditing
{
def copy(userName = this.userName, email = this.email) {
val copiedUser = User(userName, email)
copiedUser.createTime = createTime
copiedUser
}
}
Ответ 2
Пока я не вижу другого решения, кроме Рувина, я не понимаю требования оставить конструктор args нетронутым. Это было бы наиболее естественным решением:
case class User(userName: String, email: String,
override val createTime:Timestamp = new Timestamp(System.currentTimeMillis))
extends Auditing
Если вы не хотите, чтобы пользователь мог перезаписать createTime
, вы все равно можете использовать:
case class User private (userName: String, email: String,
override val createTime:Timestamp) extends Auditing {
def this(userName: String, email: String) =
this(userName, email, new Timestamp(System.currentTimeMillis))
}
Единственным недостатком является то, что вам нужно написать new User("Joe", "[email protected]")
, поскольку основной конструктор теперь является приватным.
Ответ 3
Возможно, вам лучше не использовать класс case. Вы можете легко реализовать
функциональность, в которой вы нуждаетесь. В приведенном ниже коде реализован метод копирования, который вам нужен, конструктор без нового, скрывает исходный конструктор и создает экстрактор, чтобы вы могли использовать User в операторах case.
class User private(val userName: String,
val email: String,
val timeStamp: Timestamp =
new Timestamp(System.currentTimeMillis)) {
def copy(uName: String = userName,
eMail: String = email) =
new User(uName, eMail, timeStamp)
}
object User {
def apply(userName: String, email: String) =
new User(userName, email)
def unapply(u: User) = Some((u.userName, u.email, u.timeStamp))
}