Build Actions для всех классов, которые смешивают черту

Использование Scala Play 2.3

У меня есть коллекция модельных классов и компаньонов, которые реализуют определенную черту - DummyData

trait DummyData[T] {
  def dummy(idx: Long): T

  def dummy(idxs: List[Long]): List[T] = {
    for {idx <- idxs} yield dummy(idx)
  }
}

case class Location(locationIdx: Long)
case class Vehicle(vehicleIdx: Long, mileage: Long)

object Location extends ...
  with DummyData[Location]
{
  def dummy(idx: Long) = {
    SubscriberLocation(idx, "name-" + idx)
  }
}

object Vehicle extends...
  with DummyData[Vehicle]
{
  ...
}

У меня есть соответствующие действия, определенные в контроллере:

val dummyIdxs: List[Long] = (1L to 5L).toList

def locationDummy = Action { implicit request =>
  Ok(Json toJson Provider.dummy(dummyIdxs))
}

def vehicleDummy = Action { implicit request =>
  Ok(Json toJson Vehicle.dummy(dummyIdxs))
}
....

Все слова каждого Действия, кроме одного, являются повторяющимся кодом.

Я хотел бы иметь возможность сделать действие, которое предоставляет фиктивные данные для любого класса, который смешивается с чертой DummyData. Итак, у меня был бы метод, определенный следующим образом:

def dummyAction[T <: DummyData](modelCompanion: T) = {
  Action { implicit request =>
    Ok(Json toJson modelCompanion.dummy(dummyIdxs))
  }
}

or

object DummyActionCreator[T] extends (DummyList[T] => TxAction) { 
  def apply(model: DummyList[T]) = TxAction { implicit request =>
    Ok(Json toJson model.dummy(dummyIdxs))
  }
}

А затем сможете выполнять новые действия, просто позвонив

def locationDummy = dummyAction[Location]

or

def locationDummy = dummyAction(Location)

Какую правильную функцию scala я должен использовать для достижения этой цели? Нужно ли мне сделать шаг назад и изменить черту?

Я пробовал несколько вариантов этого, но ошибка, которая чаще всего поражает меня, заключается в том, что DummyData требует параметров типа. Если бы я мог изменить трейт так, чтобы он не нуждался в параметрах типа, это было бы желанным решением, но я думаю, что это необходимо.


person Bill Frasure    schedule 18.03.2015    source источник


Ответы (1)


Что вам нужно, так это функция, называемая «экзистенциальными типами». Вы можете прочитать приличное объяснение (это не тривиальная концепция, поэтому я не нашел волшебного блога, который сразу бы все понял) здесь.

Следующий код делает то, что вы хотите, и печатает «3»

  trait DummyData[T] {
     def dummy(idx: Long): T

     def dummy(idxs: List[Long]): List[T] = {
        for {idx <- idxs} yield dummy(idx)
     }
  }

  object Test extends DummyData[Int]
  {
     override def dummy(idx: Long): Int = 3
  }

  def dummyAction(modelCompanion: DummyData[T] forSome { type T}) =
  {
     modelCompanion.dummy(3)
  }

  def main(args: Array[String]): Unit =
  {
     val dummy3 = dummyAction(Test)
     print(dummy3)
  }

Ваше здоровье!

person Daniel Langdon    schedule 18.03.2015