Scala:按类型参数创建实例

时间:2017-10-17 19:58:43

标签: scala

我正在尝试创建一个通用方法来通过指定的类型参数创建类实例。

代码更改条件: *尽可能减少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()
        ^

2 个答案:

答案 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,只需搜索ClassTagTypeTag即可获得更多信息。

但是,这比其他答案中给出的解决方案更不安全:如果类没有构造函数使用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