1

我正在对将保留在数据库中的实体进行建模。以用户实体为例,我想以这种方式使用它们:

val userBeforePersisting = new User("Joe", "joe@gmail.com")

// DB access code (where rs is a ResultSet)
val foundUser = new User(rs.getLong("id"), rs.getString("name"), rs.getString("email"))

我想使用相同的用户代码(即最小化代码重复),同时拥有两种类型的用户:

  1. 预持久化用户没有 ID
  2. 从数据库中检索到的持久用户有一个 ID

我想在编译时尽可能严格地执行这一点。

我希望能够对所有用户一视同仁,除非我尝试从非持久用户那里获取 ID,否则将引发错误或无法编译。

我想避免像这样制作单独的课程

class NewUser(val name: String, val email: String)
class PersistedUser(val id: Long, val name: String, val email: String)

由于代码重复(姓名和电子邮件字段),我不喜欢这个解决方案。

这是我的想法:

class User(val id: Long, val name: String, val email: String) {
  this(name: String, email: String) = this(0l, name, email)
  this(id: Long, name: String, email: String) = this(id, name, email)
}

但是后来我的非持久用户有一个id.0l

这是另一种方法:

trait User {
  val name: String
  val email: String
}

class NewUser(val name: String, val email: String) extends User

class PersistedUser(val id: Long, val name: String, val email: String) extends User

这给了我想要的编译时检查。我不确定这是否有任何缺点。

也许我可以尝试这样的事情:

class User(val name: String, val email: String)
trait Persisted { val id: Long }
class PersistedUser(val id: Long, val name: String, val email: String)
  extends User(name, email)
  with Persisted

对这些方法有什么想法吗?我从来没有这样做过,所以我不确定我是否理解所有后果。

4

1 回答 1

3

听起来像是一个可能的用途Option

class User(val id: Option[Long], val name: String, val email: String)

所以持久化用户有一个idSome(id)而非持久化用户有None

为方便起见,您可以授予id默认值None

class User(val id: Option[Long] = None, val name: String, val email: String)

// When you have an id...
val foundUser = new User(Some(rs.getLong("id")), 
    name = rs.getString("name"), email = rs.getString("email"))

// When you don't
val userBeforePersisting = new User(name = "Joe", email = "joe@gmail.com")

// However this will throw a runtime error:
val idThatDoesntExist: Long = userBeforePersisting.id.get

这也应该适用于您的多构造函数示例:

class User(val id: Option[Long], val name: String, val email: String) {
  def this(name: String, email: String) = this(None, name, email)
  def this(id: Long, name: String, email: String) = this(Some(id), name, email)
}

我认为Option可能是有道理的,因为您想在同一个类中表达某个字段可以有值或没有值。唯一的另一种方法似乎是有两个类(可能一个从另一个继承),只有一个有一个id字段。

于 2012-12-12T05:45:03.760 回答