我正在尝试创建一个通用方法来通过指定的类型参数创建类实例。
代码更改条件: *尽可能减少P1-P3类的变化 它是一个遗留代码,下面的代码只是一个原型,理想情况下对这些类没有任何改变。
请参阅下面的代码。
trait P {
def run() : Unit = ???
}
class P1 (cfg : String ) extends P {
override def run() : Unit = {
println("1")
}
}
class P2 (cfg : String )extends P {
override def run() : Unit = {
println("2")
}
}
class P3 (cfg : String ) extends P {
override def run() : Unit = {
println("3")
}
}
def executor[T <: P](cfg: String): Unit = {
new T(cfg).run()
}
executor[P1]("someCfg")
executor[P2]("someCfg")
executor[P3]("someCfg")
这是我得到的错误:
Error:(26, 10) class type required but T found
new T(cfg).run()
^
Error:(53, 10) class type required but T found
new T(cfg).run()
^
答案 0 :(得分:4)
你可以这样做:
import scala.reflect.ClassTag
def executor[T <: P](cfg: String)(implicit tag: ClassTag[T]): Unit = {
tag.runtimeClass.getConstructor(classOf[String]).
newInstance(cfg).asInstanceOf[T].run()
}
并使用它:
executor[P1]("someCfg")
executor[P2]("someCfg")
executor[P3]("someCfg")
阅读http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html,只需搜索ClassTag
和TypeTag
即可获得更多信息。
但是,这比其他答案中给出的解决方案更不安全:如果类没有构造函数使用String
,它将在运行时失败。
答案 1 :(得分:3)
由于类型删除,有关T
的信息在运行时丢失,因此无法实例化。
为了满足您的要求,只需更改P1
- P3
类,您就必须将某种工厂功能传递给executor
:
def executor[T <: P](cfg: String)(fct: String => T): Unit = {
fct(cfg).run()
}
在这种情况下,呼叫方将改为:
executor("someCfg")(new P1(_))
executor("someCfg")(new P2(_))
executor("someCfg")(new P3(_))
没有更改P1
- P3
类。
输出:
1
2
3