13

to nie działa zgodnie z oczekiwaniami (od Próbuję zadzwonić pakiet prywatnej run z zewnątrz Services):Scala: Pakiety Dostęp widoczne metody poprzez typów strukturalnych poza pakietem

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

val obj = new Services.HelloPrinter 

Ale, o dziwo to działa:

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

chciałbym powiedzieć, jest to błąd w kompilatorze ponieważ jak HelloPrinter nie pasuje do typu strukturalnego z powodu zasad widoczności pakiet, to nie powinien skompilować w ogóle!

Oto przypadek, w którym program kompiluje ale zgłasza wyjątek środowiska wykonawczego (java.lang.NoSuchMethodException):

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

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

czy jest to cecha języka lub orzekania jestem brakujące lub legalnie błąd w Scala?

+2

Bardzo interesujące. Czy próbowałeś uruchomić z 'scala -feature' REPL? Wyraźnie widać, że istnieje odwołanie odblaskowe. Przypuszczam, że zakres i niezmienność są nie na miejscu, jeśli chodzi o refleksję. – marios

+2

No cóż, o ile mogę powiedzieć, ostrzeżenie ma na celu uczynienie cię ostrożnym przed możliwymi konsekwencjami wydajności. Rozumiem, że pomimo użycia refleksji do wykonania faktycznego wywołania w czasie wykonywania, strukturalne pisanie jest (rzekomo) tak statycznie wpisane, jak cokolwiek innego w scala, ponieważ kompilator sprawdzi, czy podpisy ściśle się zgadzają (a zatem tylko odblaskowe wywołanie może osiągnąć sukces). O ile oczywiście nie wykonasz wyraźnego downcastu do typu strukturalnego. Jednak tutaj nie ma obsady, kompilator po prostu wydaje się pomijać sprawdzanie widoczności metody. –

+0

Drugi przykład, który powiedziałeś, rzuca 'NoSuchMethodException', nie kompiluje się dla mnie (w REPL 2.10.4 i 2.11.6). –

Odpowiedz

4

Na poziomie JVM widoczność nie ma zasięgu do otaczających instancji/typów. Kompilator Scala wygeneruje w tym przypadku publiczną metodę i wewnętrznie poradzi sobie z tą widocznością.

Jeśli używasz typów strukturalnych, kompilator będzie odbijał dostęp do elementów tego typu. Nie będzie sprawdzać flag specyficznych dla Scala, ale tylko te zdefiniowane w kodzie bajtowym Java.

Nie wspomniano, której wersji kompilatora Scala używasz, ale zakładam, że jest to błąd w konkretnej wersji. Otrzymuję taki sam wynik, jak Jasper-M, gdy próbuję go skompilować. Powodem jest to, że metoda generowana przez kompilator jest w tym przypadku poprzedzana nazwą typu, tj. HelloPrinter$$run. Poniższy kod zostanie wykonany:

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

Ponownie kompilator Scali generuje publiczną metodę i wewnętrznie zarządza widocznością. Nie jest to funkcja, ale raczej błąd, który kompilator nie sprawdza wewnętrznej widoczności Scala dla typów strukturalnych.

+1

Czy jest już otwarty problem? Jeśli nie, mogę złożyć jeden? – pathikrit

Powiązane problemy