2012-12-12 45 views
1

我正在建模將保留在數據庫中的實體。使用用戶實體作爲一個例子,我想用這種方式與他們一起工作:只讀實體的Scala數據模型

val userBeforePersisting = new User("Joe", "[email protected]") 

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

但後來我未堅持用戶有0lid

這裏的另一種方法:

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 

任何思考這些方法?我從來沒有這樣做過,所以我不確定我是否理解了所有的後果。

+0

你不喜歡最後一種方法?是'val name:String,val email:String'出現兩次的次要代碼重複嗎? – Faiz

回答

3

聽起來像可能使用Option

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

所以堅持用戶擁有的Some(id)id而非持續的用戶有None

爲方便起見,你能給idNone默認值:

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 = "[email protected]") 

// 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字段。

+0

感謝您的反饋@Faiz。我曾考慮過Options,我認爲這是一個好方法。我不喜歡這種方法的事情是,我對用戶的大部分處理都是持久用戶,我想避免所有的.get調用。我確實給了你一票,因爲這是一個可靠的解決方案。 –

+0

@three_cups_of_java我明白了 - 好吧,我猜''Option'的慣用用法通常會避開'.get'來支持'foreach' /'map' /'filter'等 - 但我現在明白你想要一個'PersistedUser '類你認爲理所當然'ID'字段表示一個真實的ID保持。 – Faiz