13

Questo non funziona come previsto (dal momento che sto cercando di chiamare un pacchetto privato run dall'esterno Services):Scala: pacchetto Accesso metodi visibili attraverso tipologie strutturali al di fuori del pacchetto

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

val obj = new Services.HelloPrinter 

Ma, sorprendentemente questo funziona:

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

direi, è un bug nel compilatore poiché come HelloPrinter non corrisponde al tipo strutturale a causa delle regole pacchetto di visibilità, non dovrebbe compilare a tutti!

Ecco un caso in cui il programma viene compilato, ma genera un'eccezione di runtime (java.lang.NoSuchMethodException):

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

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

Si tratta di una caratteristica del linguaggio o di regola mi manca o legittimamente un bug in Scala?

+2

Molto interessante. Hai provato a girare con REPL di scala? Mostra chiaramente che c'è una chiamata riflessiva invocata. Immagino che l'ambito e l'immutabilità siano tutti fuori dalla finestra quando si parla di riflessione. – marios

+2

Beh, per quanto posso dire, l'avvertimento è più inteso a renderti cauto sulle possibili conseguenze delle prestazioni. La mia comprensione è che, nonostante l'uso della reflection per eseguire l'effettiva chiamata in fase di esecuzione, la tipizzazione strutturale è (presumibilmente) tipizzata staticamente come qualsiasi altra cosa in scala, perché il compilatore verificherà che le firme corrispondano rigorosamente (e quindi la chiamata riflessiva può solo avere successo). A meno che, naturalmente, non si esegua un downcast esplicito a un tipo strutturale. Comunque qui non c'è cast, il compilatore sembra semplicemente omettere di verificare la visibilità del metodo. –

+0

Il secondo esempio che tu dici di non eseguire una 'NoSuchMethodException' per me (nel REPL 2.10.4 e 2.11.6). –

risposta

4

Sul livello JVM la visibilità con scope per istanze/tipi circostanti non esiste. Il compilatore Scala genererà un metodo pubblico in questo caso e gestirà internamente questa visibilità.

Se si utilizzano tipi strutturali il compilatore accederà in modo riflessivo ai membri di questo tipo. Non controllerà i flag di visibilità specifici di Scala ma solo quelli definiti nel bytecode Java.

Non hai menzionato quale versione del compilatore Scala stai usando, ma presumo che si tratti di un bug nella tua versione specifica. Ottengo lo stesso risultato di Jasper-M quando provo a compilarlo. Il motivo è che il metodo generato dal compilatore è in realtà preceduto dal nome del tipo, ovvero HelloPrinter$$run in questo caso. Il seguente codice eseguirà:

val x: { def HelloPrinter$$run: String } = new HelloPrinter 
x.run 

Anche in questo caso il compilatore Scala solo genera un metodo pubblico e gestisce visibilità internamente. Non è una funzionalità, ma piuttosto un bug che il compilatore non controlla la visibilità interna di Scala per i tipi strutturali.

+1

Esiste già un problema aperto? In caso contrario, posso scriverne uno? – pathikrit