2016-02-27 46 views
1

以下工作:類具有其自己的上下文約束

trait Context[T] { 
    def context(x: T): String 

class Foo[T : Context](x: T) { 
    def bar() = implicitly[Context[T]].context(x) 
} 

implicit val c = new Context[Double] { 
    override def context(x: Double): String = "I am a double" 
} 

val f = new Foo(2.0) 
f.bar() // I am a double 

所以我想......是不是也有可能,如果我建立一個類誰都有自己的語境定義呢?

object Foo { 
    def apply[T : Context](x: T) = new Foo[T](x) 
    def apply[T](x: T, contextFunc: T => String): Foo[T] with Context[T] = new Foo[T](x) with Context[T] { 
     override def context(x: T): Double = contextFunc(x) 
    } 
} 

val f2 = Foo[Double](2.0, x => "I am still a double") 

但它開始抱怨第二個應用函數中隱含的證據丟失。我可以想象,因爲它看起來開始使Foo-class第一,然後開始創建Context [T]特性。

有沒有辦法解決這個問題?換一種說法?有沒有辦法構建一個擁有自己Context [T]的Foo類?

+0

語境[T]是一個類型類=你沒有在混合類型類在各自類,你會失去「正交性」。您可以在Foo的伴隨對象中聲明Context [T] double:object Foo {implicit val c = new Context [Double] ...},因爲scala隱式查找規則http://docs.scala-lang.org/tutorials/FAQ/found-implicits –

+1

@TrustNoOne Scala在那裏找不到它。 'Context [Double]'沒有提到'Foo',所以Scala不會在同伴對象Foo中尋找它。 – Kolmar

+0

whooops ..你其實是對的。我要再喝一杯咖啡 –

回答

2

最簡單的方法可能是構建一個上下文對象,並明確地把它作爲一個參數,構建Foo時:

def apply[T](x: T, contextFunc: T => String): Foo[T] = 
    new Foo(x)(new Context[T] { 
    def context(t: T) = contextFunc(t) 
    }) 
+0

太好了,我會嘗試。我不知道這是可能的,但這只是合乎邏輯的課程。編輯:它的工作原理!謝謝! – avanwieringen