Pourquoi le code suivant ne reprend pas la val implicite avec le supertype le plus proche ?
class A
class B extends A
trait TC[-T] { def show(t: T): String }
implicit val showA = new TC[A] { def show(a: A): String = "it's A" }
implicit val showB = new TC[B] { def show(b: B): String = "it's B" }
def doit[X](x: X)(implicit tc: TC[X]): Unit = println(tc.show(x))
doit(new A) // "it's A" as expected
doit(new B) // "it's A" ... why does this not give "it's B" ???
Si vous faites TC
invariant (c'est-à-dire trait TC[T] (...)
), alors cela fonctionne bien et doit(new B)
retourne "c'est B" comme prévu.
En ajoutant un autre implicite pour le type Any
ce problème est encore plus extrême :
class A
class B extends A
trait TC[-T] { def show(t: T): String }
implicit val showA = new TC[A] { def show(a: A): String = "it's A" }
implicit val showB = new TC[B] { def show(b: B): String = "it's B" }
implicit val showAny = new TC[Any] { def show(x: Any): String = "it's Any" }
def doit[X](x: X)(implicit tc: TC[X]): Unit = println(tc.show(x))
doit(new A) // "it's Any" ... why does this not give "it's A" ???
doit(new B) // "it's Any" ... why does this not give "it's B" ???
Et encore une fois, ça marche bien si TC
est invariant.
Qu'est-ce qui se passe ici, et comment le résoudre ? Mon objectif est d'avoir un système contravariant TC
qui choisit implicitement le supertype approprié le plus proche.