13

Das wie erwartet funktioniert nicht (da ich ein Paket privaten run von außen Services rufen versuche):Scala: sichtbare Methoden durch Strukturtypen außerhalb des Pakets Zugriff Paket

object Services { 
class HelloPrinter { 
    private[Services] def run = "Hello" 
    } 
} 

val obj = new Services.HelloPrinter 

Aber überraschenderweise das funktioniert:

val obj: {def run: String} = new Services.HelloPrinter 
obj.run 

ich würde sagen, da sein um einen Fehler in dem Compiler als HelloPrinter den Strukturtyp wegen Paket Sichtbarkeitsregeln nicht übereinstimmt, ist es überhaupt nicht kompilieren soll! Hier

ist ein Fall, in dem das Programm kompiliert, aber es wirft eine Laufzeitausnahme (java.lang.NoSuchMethodException):

class HelloPrinter { 
    private[HelloPrinter] def run = "Hello" 
} 

val obj: {def run: String} = new HelloPrinter 
obj.run 

Ist dies eine Sprache-Funktion oder ausschließen mir fehlt oder berechtigterweise einen Fehler in Scala?

+2

Sehr interessant. Hast du versucht mit "scala -feature" REPL zu laufen? Es zeigt deutlich, dass ein reflektierender Aufruf aufgerufen wird. Ich denke, Scoping und Unveränderbarkeit sind alle aus dem Fenster, wenn es um die Reflexion geht. – marios

+2

Nun, soweit ich das beurteilen kann, soll die Warnung eher dazu dienen, Sie vor den möglichen Leistungsfolgen zu warnen. Mein Verständnis ist, dass trotz der Verwendung von Reflektion, um den eigentlichen Aufruf zur Laufzeit durchzuführen, strukturelle Typisierung (angeblich) wie statisch typisiert ist wie alles andere in scala, weil der Compiler überprüft, dass die Signaturen genau übereinstimmen (und somit nur der reflektierende Aufruf gelingen). Es sei denn, Sie führen einen expliziten Downcast zu einem Strukturtyp durch. Da hier jedoch kein Cast vorliegt, scheint der Compiler die Sichtbarkeit der Methode einfach zu überspringen. –

+0

Das zweite Beispiel, das Sie sagen, wirft eine 'NoSuchMethodException' kompiliert nicht für mich (in 2.10.4 und 2.11.6 REPL). –

Antwort

4

Auf der JVM-Ebene existiert keine Sichtbarkeit für umgebende Instanzen/Typen. Der Scala-Compiler erzeugt in diesem Fall eine öffentliche Methode und behandelt diese Sichtbarkeit intern.

Wenn Sie Strukturtypen verwenden, greift der Compiler reflektiv auf die Elemente dieses Typs zu. Scala-spezifische Sichtbarkeits-Flags werden nicht geprüft, sondern nur diejenigen, die im Java-Bytecode definiert sind.

Sie haben nicht erwähnt, welche Version des Scala-Compilers Sie verwenden, aber ich nehme an, dass dies ein Fehler in Ihrer spezifischen Version ist. Ich bekomme das gleiche Ergebnis wie Jasper-M, wenn ich versuche es zu kompilieren. Der Grund dafür ist, dass der Methode, die vom Compiler generiert wird, tatsächlich der Typname vorangestellt ist, d. H. HelloPrinter$$run in diesem Fall. Der folgende Code wird ausgeführt:

Wieder generiert der Scala-Compiler nur eine öffentliche Methode und verwaltet die Sichtbarkeit intern. Es ist kein Feature, sondern ein Fehler, dass der Compiler die Scala-interne Sichtbarkeit für Strukturtypen nicht überprüft.

+1

Gibt es bereits ein offenes Problem? Wenn nicht, kann ich einen einreichen? – pathikrit