2016-02-10 26 views
0

我試圖採取現有的特徵層次結構(我無法控制)並在頂層注入方法(然後在每個點上覆蓋該方法在需要定製治療的層次結構中)。這些特徵隱含地使用。下面是一個修剪過的示例,顯示特徵層次結構設置和隱含用法;然後我(失敗)嘗試注入方法。使用implicits注入特徵層次結構的多個級別的方法


定義與未實現的方法,一個孩子性狀與指定類型和該方法的一個實施形式的父性狀。創建一個隱含的兒童特質。

trait ParentTrait[T] { 
    def doSomething1(x: T): T 
} 

trait ChildTrait extends ParentTrait[Double] { 
    override def doSomething1(x: Double): Double = { 
    return x + 1.0 
    } 
} 

implicit object ChildTrait extends ChildTrait 

定義一個類和函數來隱式使用Parent Trait並調用該方法。

class Utilizer1() { 
    def utilize[T](x: T)(implicit trt: ParentTrait[T]): Unit = { 
    println(trt.doSomething1(x)) 
    } 
} 

調用方法,指定類型(Double),它將隱式地拾取Child Trait。 (這工作得很好。)

new Utilizer1().utilize[Double](1.0) 

這就是事情不工作:「注入」新的方法到父特質,並在兒童特質覆蓋它。 (顯然,這是不是這樣做的正確方法 - 如何做到這一點的一部分)

implicit class BetterParentTrait[T](trt: ParentTrait[T]) { 
    def doSomething2(x: T): T = ??? 
} 
implicit class BetterChildTrait(trt: ParentTrait[Double]) extends BetterParentTrait[Double](trt) { 
    override def doSomething2(x: Double): Double = { 
    return x + 2.0 
    } 
} 

定義一個類和函數隱含使用父特質,並呼籲第二種方法。

class Utilizer2() { 
    def utilize[T](x: T)(implicit trt: ParentTrait[T]): Unit = { 
    println(trt.doSomething2(x)) 
    } 
} 

調用方法,指定類型(雙精度型)。它不隱式地拾取子特質,而是拋出一個NotImplementedError。所以它找到了doSomething2方法(沒有編譯錯誤),但它不尊重層次結構,並使用頂層的未實現形式。

new Utilizer2().utilize[Double](1.0) 

回答

0

您正在執行聚合而不是繼承。

BetterParentTrait[T](trt: ParentTrait[T])

這意味着utilize方法不會看到你的隱含類,因爲它有不同的父/接口。 它必須實現ParentTrait類才能隱式傳遞給所提到的方法。

implicit class BetterParentTrait[T] extends ParentTrait[T]{ 
    def doSomething(x: T): T = ??? 
    def doSomething2(x: T): T = ??? 
} 
0

這有幫助嗎?

object MainUtilizers { 

    trait ParentTrait[T] { 
    def doSomething1(x: T): T 
    } 

    trait ChildTrait extends ParentTrait[Double] { 
    override def doSomething1(x: Double): Double = { 
     return x + 1.0 
    } 
    } 


    trait BetterParentTrait[T] { 
    def doSomething2(x: T): T = ??? 
    } 

    trait BetterChildTrait extends BetterParentTrait[Double] { 
    override def doSomething2(x: Double): Double = { 
     return x + 2.0 
    } 
    } 

    //implicit object ChildTrait extends ChildTrait // Commented to avoid 2 implicits for ParentTrait[Double] 

    implicit object BetterChildTrait extends BetterChildTrait with ChildTrait 

    class Utilizer1() { 
    def utilize[T](x: T)(implicit trt: ParentTrait[T]): Unit = { 
     println(trt.doSomething1(x)) 
    } 
    } 
    class Utilizer2() { 
    def utilize[T](x: T)(implicit trt: BetterParentTrait[T]): Unit = { 
     println(trt.doSomething2(x)) 
    } 
    } 

    def main(args: Array[String]) { 
    new Utilizer1().utilize[Double](1.0) 

    new Utilizer2().utilize[Double](1.0) 
    } 
} 
+0

這適用於我的實際問題,這是非常有用的。如果不需要在Utilizer2中指定BetterParentTrait將會很好 - 我不能動搖那種必須有某種方式來實現這一點的感覺,但我對Scala也很陌生,所以我可能只是錯了! –

+0

很高興知道它有幫助。 明天我會再試一次,看看我能不能做出你想要的。雖然我不確定優勢。 –

+0

對不起,我沒有找到在Utilizer2中使用ParentTrait的方法。當您添加doSomething2時,您將其有效地添加到ChildTrait而不是ParentTrait [T],因此只有默認實現在範圍內。 –

相關問題