2017-03-06 2 views
1

Ich definiere implicits in Companion-Objekten, die für alle Typen außer AnyVals wie Long und Double etc. aufgelöst werden. Ich bin mir nicht ganz sicher, warum das der Fall ist? Gibt es unterschiedliche Auflösungsregeln für AnyVals?Scala implizite Auflösung für AnyVal anders?

class X(val i:Int) { 
    def add[T](implicit x:SomeType[T])=println(x) 
} 
object X { 
    implicit def xx = XType 
    implicit def ll = LType 
    implicit def dd = DType 
} 

object Console { 
    def main(args: Array[String]): Unit = { 
    new X(3).add[X] // works fine 
    new X(3).add[Long] // error Error:(16, 16) could not find implicit value for parameter x: com.x.SomeType[Long] 
    new X(3).add[Double] // error Error:(16, 16) could not find implicit value for parameter x: com.x.SomeType[Double] 
    } 
} 

sealed trait SomeType[T] 

case object XType extends SomeType[X] 
case object LType extends SomeType[Long] 
case object DType extends SomeType[Double] 

Antwort

3

Der Compiler weiß nicht, wie diese beiden implicits innerhalb object X zu beheben:

implicit def ll = LType 
implicit def dd = DType 

Aufruf new X(3).add[X] ist in der Lage ein SomeType[X] zu lösen, weil, wenn ein implizites SomeType[X] sucht, wird der Compiler nach innen schauen das Begleitobjekt von X (unter anderem, siehe Where does Scala look for implicits?), und es findet es als implicit def xx = XType.

Für SomeType[Long] kann der Compiler nicht die implizite in Rahmen finden, noch ist es innerhalb der Begleiter Objekte von SomeType oder Long, so ist es nicht. SomeType[Double] schlägt aus dem gleichen Grund fehl.

Wenn Sie import X._ innerhalb Console wird es funktionieren, denn das würde alle implits in Geltungsbereich bringen. Wenn Sie standardmäßige implizite Instanzen von SomeType für verschiedene Typen bereitstellen möchten, sollten Sie sie am besten in den Companion SomeType einfügen.

class X(val i:Int) { 
    def add[T](implicit x: SomeType[T]) = println(x) 
} 

sealed trait SomeType[T] 

object SomeType { 
    implicit case object XType extends SomeType[X] 
    implicit case object LType extends SomeType[Long] 
    implicit case object DType extends SomeType[Double] 
} 

Im Folgenden wird immer jetzt arbeiten, egal wo Sie sie nennen:

scala> new X(3).add[X] 
XType 

scala> new X(3).add[Long] 
LType 

scala> new X(3).add[Double] 
DType 

Kurz gesagt, es hat nichts mit AnyVal zu tun. Sie könnten ein SomeType[String] neben den anderen hinzugefügt haben und hatten das gleiche Problem. Der Unterschied war, dass Sie X speziell behandelten.