2016-07-25 71 views
2

我有一個特點是通用的,是這樣的:斯卡拉實例化一個具體的類從泛型類型

trait MyTrait[T] { 
    def doSomething(elems: Seq[T]) 
} 

然後我有一個對象的工廠,其定義是這樣的:

object MyTraitFactory { 
    def apply[T](param1: Boolean, param2: Boolean): MyTrait[T] = { 
    // based on the type of T, I would like to instantiate sub types 
    } 
} 

我有具體的實施,例如:

class MyStringTrait extends MyTrait[String] 

class MyIntTrait extends MyTrait[Int] 

我現在需要那個神奇的位,會尋找鍵入我的對象工廠並實例化相應的實現。有什麼建議麼?

回答

3

這可以使用隱式類型類在scala中解決。創建具體實現的工廠的特質對每個類型:

object MyTraitFactory { 

    def apply[T](param1: Boolean, param2: Boolean)(implicit factory: MyTraitCreator[T]): MyTrait[T] = { 
    // call the typeclass create method 
    factory.create(param1, param2) 
    } 

    // factory trait 
    trait MyTraitCreator[T] { 
    def create(param1: Boolean, param2: Boolean): MyTrait[T] 
    } 

    // provide an implicit factory object for the specific types: 
    object MyTraitCreator { 

    implicit object MyStringTraitCreator extends MyTraitCreator[String] { 
     override def create(param1: Boolean, param2: Boolean): MyTrait[String] = { 
     // create the String type here 
     new MyStringTrait 
     } 
    } 

    implicit object MyIntTraitCreator extends MyTraitCreator[Int] { 
     override def create(param1: Boolean, param2: Boolean): MyTrait[Int] = { 
     // create the Int type here 
     new MyIntTrait 
     } 
    } 
    } 
} 

斯卡拉「隱藏」使用隱含參數的類型類。但是爲了達到這個目的,你必須確保將隱式工廠對象保留在編譯器尋找隱含位置的地方(例如,如上所述的伴隨對象爲MyTraitCreator)。該模式在沒有implicit的情況下也能正常工作,但是隨後需要調用者在每次調用時提供具體的工廠。

該解決方案包含許多鍋爐板代碼,但在編譯時靜態工作,不會遭受類型擦除。它甚至帶有scala中的語法糖:

def apply[T: MyTraitCreator](param1: Boolean, param2: Boolean): MyTrait[T] = { 
    // call the typeclass create method 
    implicitly[MyTraitCreator[T]].factory.create(param1, param2) 
}