2015-03-18 2 views
3

utilisant Scala Lecture 2.3Construire Actions pour toutes les classes qui MIXIN un trait

J'ai une collection de classes de cas du modèle & des compagnons qui mettent en œuvre un trait particulier - 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] 
{ 
    ... 
} 

I ont des actions correspondantes définies dans un contrôleur:

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

Tous les mots sauf un de chaque Action sont des codes en double.

Je voudrais être en mesure de faire une action qui fournit des données fictives pour toute classe qui se mélange dans le trait DummyData. Je voudrais donc avoir une méthode définie comme ceci:

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

ou

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

Et puis être en mesure de faire les nouvelles actions en appelant simplement

def locationDummy = dummyAction[Location] 

ou

def locationDummy = dummyAction(Location) 

Quelle est la fonctionnalité scala appropriée que je devrais utiliser pour réaliser ceci? Dois-je prendre du recul et changer le trait?

J'ai essayé plusieurs variantes de ceci, mais l'erreur qui me frappe le plus souvent est DummyData nécessitant des paramètres de type. Si je pouvais modifier le trait pour qu'il n'ait pas besoin de paramètres de type, ce serait une solution bienvenue, mais je pense que c'est nécessaire

Répondre

1

Ce que vous voulez, c'est une fonctionnalité appelée "types existenciels". Vous pouvez lire une explication décente (ce n'est pas un concept trivial, donc je n'ai pas trouvé un blog magique qui le rend immédiatement clair) here.

Le code suivant fait ce que vous voulez et imprime "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) 
    } 

Cheers!