Scala: метод конструктора с опцией - PullRequest
3 голосов
/ 08 октября 2011

Избегая обычного 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 { ... }
}

Это означает, что вы можете:

  1. зная и идентификатор и имя записи, создать объект, представляющий ее,
  2. зная только идентификатор записи, вы можете построитьобъект rep из DB и
  3. , если вы не предоставите идентификатор, ваш объект будет в несинхронизированном состоянии и синхронизируется после того, как произойдет добавление / обновление.

1-й конструктор зависит от операции с БД, поэтому 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
   } 
}

Имеет ли это смысл?Как бы вы это реализовали?

Ответы [ 2 ]

8 голосов
/ 08 октября 2011

Вы можете сделать это из сопутствующего объекта вашего класса:

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
4 голосов
/ 08 октября 2011

У Дирка правильная идея, использовать объект-компаньон как фабрику. Хотя можно немного улучшить дизайн:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...