2014-03-31 7 views
5

Lassen Sie uns diesen Code betrachten:Warum müssen wir explizit implizite Konvertierungen mit impliziten Parametern von Begleitobjekten importieren? Seltsam.

class A 
object A{ 
    implicit def A2Int(implicit a:A)=1 
    implicit def A2String(a:A)="Hello" 
} 

object Run extends App{ 
    implicit val a: A =new A 

    import A.A2Int 
    // without this import this code does not compile, why ? 
    // why is no import needed for A2String then ? 

    def iWantInt(implicit i:Int)=println(i) 
    def iWantString(implicit s:String)=println(s) 

    iWantInt 
    iWantString(a) 
} 

Es läuft und Drucke:

1 
Hello 

Nun, wenn wir die Linie

Kommentar aus
import A.A2Int 

wir einen Kompilierungsfehler erhalten dann:

enter image description here

Mit der Zeile auskommentiert, warum kann Scala A.A2String nicht finden, wenn es A.A2Int finden kann?

Wie kann dieses Problem behoben werden?

Danke fürs Lesen.

Antwort

3

Der Unterschied ist, dass, wenn Sie iWantString(a) tun, der Compiler bekommt einige Startpunkt zu arbeiten: Sie übergeben explizit a, die der Compiler weiß, ist vom Typ A. Vorausgesetzt, dass iWantString eine String und nicht eine A dauert, wird der Compiler für eine implizite Konvertierung von A zu String suchen, um es einzufügen und den Aufruf erfolgreich zu machen. Implizite Suchregeln geben an, dass der Compiler (unter anderem) im Companion-Objekt der Klasse A suchen muss, da der Typ A der Quelltyp der Konvertierung ist. Hier wird die implizite Konvertierung A2String gefunden. Was Sie daraus erhalten müssen ist, dass es nur, weil Sie eine Instanz von A übergeben haben, dass der Compiler wusste, nach impliziten Konvertierungen in das Companion-Objekt A zu suchen.

Wenn Sie nur iWantInt tun, hat der Compiler keinen Grund, in A zu suchen, so wird es nicht Ihre Methode A2Int (und wie keine andere Methode/Wert im Rahmen stellt einen impliziten Wert vom Typ Int, Kompilation dann nicht finden).

Weitere Informationen zu impliziten Suchregeln finden Sie unter . Siehe die scala-Spezifikation unter http://www.scala-lang.org/docu/files/ScalaReference.pdf (Kapitel 7.2). Hier ist der relevanteste Auszug:

The implicit scope of a type T consists of all companion modules (§5.4) of classes that are associated with the implicit parameter’s type.

+2

Darüber hinaus wird der Compiler nicht mehr als eine implizite ausführen * Lookup * um Typen anzupassen, während Sie implizite Lookups für 'iWantInt' haben: eine implizite Lookup zu transformieren 'A' zu' Int' und eine implizite Suche, um den Parameter von 'iWantInt' zu finden. Im Fall von "iWantString" gibt es nur eine implizite Suche, die "A" in "String" umwandelt. –

+1

Dies ist falsch. Ist Ihnen aufgefallen, dass der Code nur mit zusätzlicher Importanweisung kompiliert wird? Der Compiler führt nicht mehr als eine implizite Suche ** alleine aus, das ist richtig. Aber hier fragt die erste Konvertierung nach einem impliziten Wert vom Typ 'A', der die zweite implizite Suche startet. –

+0

Sie haben Recht damit, was ich meinte ist, dass der Compiler zuerst eine implizite Umwandlung von "A" zu "Int" finden müsste, um einen impliziten Int-Parameter zu finden (ohne den Import). Dies ist eine Abhängigkeit zwischen diesen beiden impliziten Suchvorgängen, da Sie die erste nicht auflösen können, ohne die zweite zu lösen. Die beiden impliziten Lookups, die Sie beschreiben, sind nicht voneinander abhängig.Zuerst löst es den impliziten Parameter 'Int' auf (weil 'A.A2Int' importiert wurde) und löst dann die zweite implizite Suche auf, dh den impliziten Parameter von 'A.A2Int', der aufgelöst wird, weil 'val a' implizit ist . –

Verwandte Themen