2017-10-17 74 views
1

我想創建一個泛型方法來創建指定的類型參數的類實例。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() 
     ^
+1

你必須幫助編譯器。那麼類似這樣的東西:'def executor [T <:P](cfg:String)(fn:String => T):Unit = fn(cfg).run()'。然後像'executor(「someCfg」)(新的P1(_))'一樣使用它。 –

回答

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

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 
+0

我希望有一種魔術,所以它可以通過...謝謝 – Pavel

+1

它是jvm的限制,所以我懷疑它可以避免 – tkachuko

+0

它可以,實際上。看到我的答案。 –