Scala:使用特征复制案例类

时间:2012-11-02 00:48:30

标签: scala

我是Scala的新手,我有一个关于复制案例类同时保留来自特征的数据的最佳方法的问题。例如,假设我有以下内容:

trait Auditing {

  var createTime: Timestamp = new Timestamp(System.currentTimeMillis)
}

case class User(val userName: String, val email: String) extends Auditing

val user = User("Joe", "joe@blah.com")

然后我想制作一个更改了一个参数的新副本:

val user2 = user.copy(email = "joe@newemail.com")

现在,在上面的示例中,不会复制属性createTime,因为它未在User case类的构造函数中定义。所以我的问题是:假设将createTime移动到构造函数中不是一个选项,获取包含特征值的User对象副本的最佳方法是什么?

我正在使用Scala 2.9.1

提前致谢! 乔

3 个答案:

答案 0 :(得分:6)

您可以使用该行为覆盖复制方法。

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      
  }
}

答案 1 :(得分:3)

虽然我没有看到除了Reuben之外的其他解决方案,但我不明白要求保持构造函数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", "joe@blah.com"),因为主要构造函数现在是私有的。

答案 2 :(得分:0)

您最好不要使用案例类。你可以轻松实现 您自己需要的功能。下面的代码实现了你想要的复制方法,没有new的构造函数,隐藏了原始的构造函数,并创建了一个提取器,以便你可以在case语句中使用User。

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))
}