I'm trying to build following
I have a parent generic class
abstract class ResultProvider[+T: Writes](db: DB) {
def get(id: Long): Future[Seq[T]]
}
And some implementations, e.g.
class LengthProvider(db: DB) extends ResultProvider[LengthResult](db){
override def get (userId: Long): Future[Seq[LengthResult]] = ...
}
object LengthProvider extends ((DB) => DisciplinePredictor) {
override def apply(db: DB) = new LengthProvider(db)
}
I have following configuration map:
val providers: Map[String, ((DB) => ResultProvider[???])] = Map(
"length" -> LengthProvider,
"width" -> WidthProvider,
...
)
My question is what should I put in place of ???. Ideally, it should be something like T : Writes
, as I only care that this type has Writes
implicit implemented, as I'm going to Json.toJson
it. It will compile with Any
, but then the information that the class should implement Writes
implicit is lost.
Or should I use a different approach? I could probably create a superclass for all my result case classes (e.g.LengthResult
), but I want to get away with the implicits.
You should be able to write ResultProvider[_]
(search for "existential types" if you are unfamiliar with this syntax), but you'll need to give a name to the implicit:
abstract class ResultProvider[+T](db: DB)(implicit val writes: Writes[T]) { ... }
Elsewhere:
val provider: ResultProvider[_] = providers("length")
import provider.writes // makes the implicit visible here
...
You might need to help the compiler (or yourself, if you need to name the type) by providing a type variable:
providers("length") match {
case provider: ResultProvider[a] =>
import provider.writes
...
}