Scala Playframework插件和泛型
我想实现这样一种情况:带有泛型参数的抽象类和实现该类的具体插件 例如:Scala Playframework插件和泛型,scala,generics,playframework,scala-2.10,Scala,Generics,Playframework,Scala 2.10,我想实现这样一种情况:带有泛型参数的抽象类和实现该类的具体插件 例如: abstract class BasePlugin[T] extends Plugin { def d: T } class MyPlugin(app: Application) extends BasePlugin[String] { val d = "test" } 我的愿望是实现以下目标: val plugin = app.plugin[BasePlugin[String]] //Ok, plugin =
abstract class BasePlugin[T] extends Plugin {
def d: T
}
class MyPlugin(app: Application) extends BasePlugin[String] {
val d = "test"
}
我的愿望是实现以下目标:
val plugin = app.plugin[BasePlugin[String]]
//Ok, plugin = Some(MyPlugin)
val plugin = app.plugin[BasePlugin[Int]]
//KO, plugin = None
当然这不会发生,因为myPlugin使用任何类型作为参数(类型擦除?)。
无论如何,找到一种技术来获得上述信息对我来说是非常有效的。有什么想法吗?play plugin api在查找属于Java一部分的插件时使用Class.isAssignableFrom,因此Scala获得ClassTag/TypeTags不会有帮助 也许您可以创建自己的子插件格式,例如:
trait SubPlugin[T] {
def doSomething(t: T) {}
}
trait MetaPlugin {
private val subPlugins: Seq[(Class[_], SubPlugin[_])] = ???
def subPlugin[T](implicit classTag: ClassTag[T]): Option[SubPlugin[T]] = {
subPlugins.collectFirst {
case (c, p) if c.isAssignableFrom(classTag.runtimeClass) => p.asInstanceOf[SubPlugin[T]]
}
}
}
object MetaPlugin {
def apply[T](implicit app: play.api.Application, classTag: ClassTag[T]): Option[SubPlugin[T]] =
app.plugin[MetaPlugin].flatMap(_.subPlugin[T])
}
object AndThenSomeWhere {
import play.api.Play.current
MetaPlugin[String].map(_.doSomething("a string"))
}
Scala有一种称为ClassTag的东西,它使得即使应用程序已经编译,也可以保留类型信息。它在scala 2.10之前被称为Manifest。也许你可以用它们来解决这个问题?!