2015-10-24 21 views
17

Ich habe zwei Möglichkeiten (eine weniger als die andere) der Erklärung implicit für Typenklassenmuster in Scala gesehen.Scala implizites Objekt vs implizit val

implicit val instance1 = new Typeclass { def do = ??? } 
implicit object instance2 extends Typeclass { def do = ??? } 

Wie unterscheiden sie sich? Soll man für bestimmte Zeiten einander den Vorzug geben? Ich finde implicit val viel häufiger verwendet als implicit object und ich habe noch viele Ressourcen über implicit object finden.

Antwort

8

Ein Unterschied besteht darin, dass die object-Version langsam initialisiert wird, d. H. Ihr Konstruktor wird erst bei der ersten Verwendung aufgerufen. Zum Beispiel:

trait Incrementer[T] { 
    def inc(x: T) 
} 

def increment[T](x: T)(implicit ev: Incrementer[T]) = ev.inc(x) 

implicit object IntIncrementer extends Incrementer[Int] { 
    println("IntIncrementer is being constructed...") 

    def inc(x: Int) = x + 1 
} 

implicit val DoubleIncrementer extends Incrementer[Double] { 
    println("DoubleIncrementer is being constructed...") 

    def inc(x: Double) = x + 1D 
} 

Beachten Sie, dass die Nachricht nicht von IntIncrementer werden sehen, bis es verwendet wird, z.B.

increment(1) //this prints "IntIncrementer is being constructed..." 

Die Nachricht von DoubleIncrementer wird jedoch angezeigt werden, wenn sie definiert ist. So ist die Initialisierung von implicit object faul, während die Initialisierung von implicit val streng ist.

+1

Also, die Entscheidung, ein 'implizites'' Objekt' gegenüber 'val' zu verwenden, hängt davon ab, ob man eine faule oder strikte Initialisierung vorzieht? –

+2

Das könnte eine Überlegung sein (obwohl Sie '' lazy val'' verwenden können, um Faulheit mit 'val' zu bekommen), aber nicht die einzige. Zum Beispiel kann ein "val" Mitglied in einer Unterklasse außer Kraft gesetzt werden, während ein "object" Mitglied dies nicht kann. Ich bin mir sicher, dass es noch viele andere Unterschiede gibt. –