2011-10-08 58 views
3

避免通常的ORM因爲不相關的原因,我試圖編寫一個既可以呈現來自數據庫的數據又可以向其中添加/更新數據的類(這首先是個好主意?)。Scala:構造方法與選項

class Car (val _id:ID, val _name:String = "") { 
    def this(_id:ID) = { 
     val car = DB.fetchCar(_id) 
     this(_id,car.name) 
    } 
    def this(_name:String) = this(null,_name) 
    def isSynced:Boolean = { ... } 
    def sync { ... } 
} 

這意味着您可以:

  1. 知道創紀錄的兩個編號和名稱,創建代表一個對象,
  2. 只知道該記錄的ID,您可以構建從數據庫中的rep對象和
  3. 如果你沒有提供一個id,你的對象將處於未初始化狀態,並且在添加/更新發生後會同步。

事情是,第一個構造函數依賴於DB操作,因此Option [Car]作爲返回類型更有意義。但據我所見斯卡拉不允許你做這樣的事情:

def this(_id:ID):Option[Car] = { 
    try { 
     val car = DB.fetchCar(_id) 
     Some(this(_id,car.name)) 
    } catch { 
     case e:Exception => None 
    } 
} 

這是否有意義?你將如何實現這一點?

回答

8

你可以從你的類的對象伴侶做到這一點:

class Car private (data: CarData) { 
    ... 
} 

object Car { 

    def apply(id: Int): Option[Car] = { 
     DB.find(id) match { 
      case Some(data) => Some(new Car(data)) 
      case _ => None 
     } 
    } 

    def apply(data: CarData): Car = { 
     new Car(data) 
    } 
} 

這允許客戶端代碼

val someId: Int = ... 
val maybeCar = Car(someId)    // Will be Option[Car] 
val someKnownData: CarData = ... 
val definitiveCar = Car(someKnownData) // Will be Car 
+0

非常有意義,也CarData你的意思打包所有的對象數據爲案例類?這聽起來不錯,但是現在的Car類更好地被用作這種類型的行爲的一個可重用的泛型類,對嗎? – parsa

+0

'CarData'只是一個無論數據/值/參數都需要的佔位符。沒有與之相關的實際設計建議......對不起,如果它帶來任何困惑。 – Dirk

+0

我看到了,無論如何謝謝 - 我從中得到了一個很酷的想法。 – parsa

4

德克有正確的想法,使用配套對象的工廠。儘管它可能在設計上提高了一下:

case class Car private (id: Option[Id], name: String) 

object Car { 
    def fetch(id: Id, name: String): Option[Car] = Some(Car(id, name)) 

    def fetch(name: String): Option[Car] = Some(Car(None, name)) 

    def fetch(id: Id): Option[Car] = try { 
    Option(DB.fetchCar(id)) //will be `None` if the fetch operation returned null 
    } catch { 
    case _ => None 
    } 
} 

用途爲:

val car1 = Car.fetch(someId, "Herbie") 

val car2 = Car.fetch("Herbie") 

val car3 = Car.fetch(someId) 

val car2withId = car2.copy(id = someNewId) 
+0

也是'Option()'部分的很棒的提示。乾杯。 – parsa