Scala:带选项的构造函数方法

par*_*rsa 3 oop orm scala

出于非相关原因避免使用通常的ORM,我正在尝试编写一个既可以从数据库中显示数据又可以向其添加/更新数据的类(这首先是一个好主意?).

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 { ... }
}
Run Code Online (Sandbox Code Playgroud)

这意味着你可以:

  1. 知道记录的id和名称,创建一个表示它的对象,
  2. 只知道记录的id,你可以从DB和.构造rep对象
  3. 如果您没有提供id,则您的对象将处于未同步状态,并在添加/更新发生后同步.

问题是,第一个构造函数依赖于DB操作,因此Option [Car]作为返回类型更有意义.但据我所知,Scala不允许你做类似的事情:

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

这有意义吗?你会如何实现这个?

Dir*_*irk 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

这允许客户端代码

val someId: Int = ...
val maybeCar = Car(someId)              // Will be Option[Car]
val someKnownData: CarData = ...
val definitiveCar = Car(someKnownData)  // Will be Car
Run Code Online (Sandbox Code Playgroud)