2010-07-18 44 views
6

我試圖創建一個使用這種方法如何在scala中的泛型方法中創建特徵的實例?

val inst = new Object with MyTrait 

這行之有效的性狀的實例,但我想在這個移動創建到發電機的功能,即。

object Creator { 
    def create[T] : T = new Object with T 
} 

我顯然會需要的清單以某種方式解決類型擦除問題,但之前,我要這個,我要2個問題運行:

  1. 即使有一個隱含的清單,斯卡拉仍然要求T是一個特質。如何添加限制來創建[T],以便T是一個特質?

  2. 如果我選擇使用Class.newInstance方法動態創建實例而不是使用「new」,我將如何在「帶T的新對象」中指定「with」?是否有可能在運行時動態創建新的混凝土混合類型?

回答

8

你不能這樣做(即使是清單)。代碼new Object with T涉及創建一個新的匿名類,代表Object with T的組合。要將它傳遞給你的create函數,你必須在運行時生成這個新類(使用新的字節碼),而且Scala沒有在運行時生成新類的功能。

一種策略可能是嘗試將工廠方法的特殊功能轉移到類的構造函數中,然後直接使用構造函數。

另一個可能的策略是創建轉換函數(隱式或其他)到你感興趣的特性使用這個類。

+0

這似乎是該語言的一個有趣的限制,但我沒有看到爲什麼它無法通過Scala中新的「動態」混合支持修復的原因。特徵代碼已經作爲靜態方法提供,所以線性化查找可以在運行時計算,而不是烘焙到類字節碼中。那麼你只需要添加運行時類型檢查,以便「asInstanceOf」起作用。 – ACyclic 2010-07-18 15:03:58

14

我不確定你的問題的動機是什麼,但你可以考慮通過一個工廠T作爲一個隱式參數。這被稱爲使用類型類別特設多態性

object Test extends Application { 
    trait Factory[T] { 
    def apply: T 
    } 
    object Factory { 
    /** 
    * Construct a factory for type `T` that creates a new instance by 
    * invoking the by-name parameter `t` 
    */ 
    def apply[T](t: => T): Factory[T] = new Factory[T] { 
     def apply = t 
    } 
    } 

    // define a few traits... 
    trait T1 
    trait T2 

    // ...and corresponding instances of the `Factory` type class. 
    implicit val T1Factory: Factory[T1] = Factory(new T1{}) 
    implicit val T2Factory: Factory[T2] = Factory(new T2{}) 

    // Use a context bound to restrict type parameter T 
    // by requiring an implicit parameter of type `Factory[T]` 
    def create[T: Factory]: T = implicitly[Factory[T]].apply 

    create[T1] 
    create[T2] 

} 

在光譜的另一端,你可以在運行時調用編譯器,如this answer詳細說明這個問題:「在斯卡拉動態混入 - ?有沒有可能」。

+0

謝謝,我可能不得不使用這種方法。 我的用例是Java代理。我想寫一個可遠程使用的圖書館。因此我需要爲我所有的類定義接口,因爲我想暴露一切,這是一個痛苦。一種解決方案是將所有東西都寫成特性,然後我可以免費獲得界面定義。創建函數的目的是在代理連接的「具體」一側實例化一個特徵。 – ACyclic 2010-07-18 15:09:18