2012-05-11 54 views
3

我想使用Scala的清單來實例化一個類型,並且當類型被視圖綁定的類型參數化時,我遇到了問題。我倒蒸餾問題下面的代碼:使用清單實例化視圖有界類型

class foo[X <% Ordered[X]]() {} 

def boo[T](implicit m : Manifest[T]) = { m.erasure.newInstance().asInstanceOf[T] } 

boo[foo[String]] 

java.lang.InstantiationException: foo 
    at java.lang.Class.newInstance0(Class.java:357) 
    at java.lang.Class.newInstance(Class.java:325) 
    . . . 

所以你可以看到,我們有一個簡單的類,foo,它是X參數;這是由Ordered [X]限定的視圖。 boo函數只是嘗試使用manifest實例化一個foo [String]的新實例。然而,當這個函數被調用時,事情變得非常糟糕,我得到的堆棧跟蹤開始,正如我所示。當foo的類型參數不是視圖有界時,實例化沒有問題。我認爲這與事實有關,因爲視圖邊界僅僅是語法糖對於X => Ordered [X]的隱式轉換的存在,並且某種程度上依賴於另一個清單的清單正在導致問題。但是,我不知道發生了什麼,或者更重要的是,如何解決它。這在斯卡拉甚至是可能的,如果不是,人們如何實現類似的東西?

回答

7

newInstance僅在T具有無參數構造函數時有效。 foo還沒有。視圖綁定<%(就像上下文綁定:)是構造函數中隱式參數的快捷方式。

class foo[X <% Ordered[X]]class foo(implicit freshName: X => Ordered[X])相同。缺少foo的無參數構造函數,newInstance失敗。

5

你可以把它的工作方式如下:

def boo[A, B[_]](implicit toOrdA: A => Ordered[A], mf: Manifest[B[A]]): B[A] = { 
    val constructor = mf.erasure.getConstructor(classOf[A => Ordered[A]]) 
    constructor.newInstance(toOrdA).asInstanceOf[B[A]] 
} 
+0

海科謝謝!在我的例子中,類型邊界還有一些額外的奇怪現象(在這個簡單的例子中沒有顯示),但是在我解決這個問題後,您的解決方案效果很好! – nomad