2011-07-31 59 views
4

Manifest上的訪問似乎從scala中的特性來說很棘手。如何在Scala中使用參數化特徵的反射?

這段代碼如何在scala中編譯?

trait SomeTraitOf[+A] { 

    def newInstanceOfA : A = /* necessary code to make it work */ 

} 

(相關,它工作正常的parametized類:

class SomeTraitOf[A : Manifest] { 

    def newInstanceOfA(implicit m : Manifest[A]) : A = 
    m.erasure.newInstance.asInstanceOf[A] 

} 

,但不與協變類型參數(+ A))

編輯:真正的東西

sealed trait RootPeerProxy[+A] extends Proxy { 

    def peer: A 
    def self = peer 
    def peerManifest[B >: A](): Option[Manifest[B]] 
    private[scalavaadin] def newInstance() : Option[A] 
} 

trait PeerProxy[+A] extends RootPeerProxy[A] { 
    override def peerManifest[B >: A](): Option[Manifest[B]] 
    override def peer(): A = this.newInstance match { 
    case None => {throw new IllegalStateException("oups")} 
    case Some(a) => a 
    } 
    private[scalavaadin] override def newInstance() : Option[A] = peerManifest map { m => m.erasure.newInstance.asInstanceOf[A] } 
} 

由於性狀不能提供參數化特徵的清單,所以實現特徵的類應該是bu我不明白。

回答

4

關於協方差

由於Manifest[A]是在參數A不變的,你不能這樣做,你直接想要的東西。通常的策略是削弱返回類型,

trait SomeTraitOf[+A] { 
    def newInstance[B >: A](implicit m: Manifest[B]): B = { 
    m.erasure.newInstance.asInstanceOf[B] 
    } 
} 

可以按如下方式使用特點,

class Parent 
class Child extends Parent 
val childBuilder = new SomeTraitOf[Child] {} 
val parentBuilder: SomeTraitOf[Parent] = childBuilder 
parentBuilder.newInstance // returns a Parent! 

關於查看邊界

從下面的評論,我想你還詢問了「視圖邊界」,這只是一種簡明的聲明隱式參數的方式。你的宣言

class SomeTraitOf[A : Manifest] { ... 

基本上轉化爲

class SomeTraitOf[A]()(implicit m0: Manifest[A]) { .... 

性狀不能有觀點界限,因爲他們不能採取任何(值)參數。但這不是一個真正的問題,因爲在你的例子中

class SomeTraitOf[A : Manifest] { 
    def newInstanceOfA(implicit m : Manifest[A]) : A = 
    m.erasure.newInstance.asInstanceOf[A] 
} 

你沒有使用視圖邊界! (您使用的參數m來代替。)如果你想使用的視圖的約束,你可以這樣來做:

class SomeTraitOf[A : Manifest] { 
    def newInstanceOfA : A = 
    implicitly[Manifest[A]].erasure.newInstance.asInstanceOf[A] 
} 
+0

'類SomeTraitOf [+ A:清單] { 高清newInstanceOfA [B> :A](implicit m:Manifest [B]):B = m.erasure.newInstance.asInstanceOf [B] }'工作正常,但特質不帶有明顯的信息。 – jwinandy

+0

好吧,我明白了,我不能直接在特性中使用它,例如'def peer():A = newInstance',但它在外面工作正常。 – jwinandy

+0

我不確定我是否理解你的問題,但我更新了我的答案並提供了更多信息。 –

相關問題