2013-04-16 34 views
2

在選擇最具體的類型時,是否有任何方法可以在類型類中使用多個合適的替代方法,而不會產生分歧的隱式擴展?它看起來像這樣多個替代方案之間的隱式搜索決策

trait A 

trait B extends A 

case class C extends B 

trait Tester[-T] {def test (t : T) : Boolean} 

object Tester{ 

    def test[T] (t : T)(implicit tester : Tester[T]) = tester.test(t) 

    implicit def ATester = new Tester[A] { 
    override def test (a : A) = true 
    } 

    implicit def BTester = new Tester[B] { 
    override def test (b : B) = false 
    } 

} 

val c = C() 
Tester.test(c) 

我想這產生假像C更接近,而不是A到B的繼承層次。

回答

2

我會提供一些解釋,說明爲什麼這會按照這種方式工作 - 其他答案有可能的解決方法。

Tester[A]被摘掉的原因Tester[B]必須與中的Tester[-T]是相反的。這意味着對於Tester[A]Tester[B]的子類,A必須是B的超類 - 就像您的代碼示例所示。

因此,當該方法test(與隱式參數)需要的Tester[C]一個亞型,替代將是Tester[B](的Tester[C]子類)和Tester[A](也亞類的Tester[C],但更具體之一)。這就是爲什麼,根據選擇最具體類型的規則,Tester[A]被選中。

如果有class D extends C,並且隱式函數返回Tester[D],如果不是參數Tester[C]的分辨率的一部分。

還有關於它的其他信息here

+0

我從你的帖子中得到我的例子應該工作,對吧?但事實並非如此。它抱怨分歧擴張。 –

+1

您的示例在Scala 2.10.1下爲我編譯並運行時沒有錯誤或警告,您是什麼意思?「它抱怨」?選擇Tester [A]並打印爲真是正確的。 –

+1

我可以驗證它是否適用於2.10.1並解析爲ATester。爲了讓BTester覆蓋ATester,請根據@ axel22的答案嘗試優先考慮您的含義......看起來現在已經消失了。遺憾的是,我認爲他是對的,但是他的BTester實例返回'true'...無論如何,搜索'LowPriorityImplicits'並查看Predef作爲示例。 – nadavwr

0

看來,這有助於

trait Tester[T] {def test (t : T) : Boolean} 

object Tester{ 

    def test[T] (t : T)(implicit tester : Tester[T]) = tester.test(t) 

    implicit def ATester[T <: A] = new Tester[T] { 
    override def test (a : T) = true 
    } 

    implicit def BTester[T <: B] = new Tester[T] { 
    override def test (b : T) = false 
    } 

} 

任何異議?