2012-10-09 13 views
17

Przepraszamy za chwytliwy tytuł. ;-)Mogę haz nie pakiet-prywatne klasy w Scala?

Chcę utworzyć klasę pakiet-prywatnego z metodą pakietu-prywatnego w Scala, więc moja klasa wygląda nieco jak poniżej:

package net.java.truevfs.ext.pace 

import ... 

private[pace] abstract class AspectController(controller: FsController) 
extends FsDecoratingController(controller) { 

    private[pace] def apply[V](operation: => V): V 

    ... // lots of other stuff 
} 

Jednakże, jeśli mogę użyć javap, by sprawdzić, co Scala kompilator skutecznie tworzy, mam coś takiego:

$ javap -classpath target/classes net.java.truevfs.ext.pace.AspectController 
Compiled from "AspectController.scala" 
public abstract class net.java.truevfs.ext.pace.AspectController extends net.java.truevfs.kernel.spec.FsDecoratingController implements scala.ScalaObject{ 
    public abstract java.lang.Object apply(scala.Function0); 
    ... 
} 

oznacza to, że choć kompilator Scala może respektować ograniczenia dostępu, mogę jeszcze nazwać tę klasę z dowolnego kodu Java, które jest oczywiste naruszenie hermetyzacji.

Czy brakuje mi czegoś? Czy istnieje sposób, aby działało to zgodnie z przeznaczeniem?

+2

+1 dla śmiesznym tytule –

Odpowiedz

15

Oprócz @ odpowiedź Regis, powodem Scala kompilator nie robi klasa pakiet-prywatnego jest bo przez Scala rządzi go może być dostępne z innych pakietów, a mianowicie: podpakietów z net.java.truevfs.ext.pace. Na przykład.

package net.java.truevfs.ext.pace.subpackage 
import net.java.truevfs.ext.pace.AspectController 

class Subclass extends AspectController { ... } 

jest legalne w Scala, ale w języku Java klasy z net.java.truevfs.ext.pace.subpackage nie może uzyskać dostępu do klas pakietu-prywatnego z net.java.truevfs.ext.pace.

+0

+1. Chciałem wskazać to samo. –

+0

Dobra uwaga - tego nie wiedziałem. –

+0

Cóż, to oznacza, że ​​pojęcie klasy paczkowo-prywatnej w ogóle nie istnieje w Scali. Szkoda, ponieważ dla mnie był to podstawowy element mojego zestawu narzędzi Java do wspierania enkapsulacji (rozumiem, że ta ochrona działa tylko na poziomie języka). –

9

Nie brakuje niczego. Wiele ograniczeń dostępu w scala nie ma odpowiednika w java ani na poziomie jvm. Dodatkowe informacje znajdują się oczywiście w pliku .class, ale są tam również adnotacje niestandardowe, które zinterpretuje tylko kompilator scala. Model obiektu scala może być tylko częściowo dopasowany do modelu obiektu jvm, a kompilator Java będzie widział tylko ten model częściowy. Powiedziałbym, że mecz jest dość blisko, a kompilator scala wykonuje bardzo dobrą robotę w interoperacyjności java, ale nic nie jest doskonałe.

+0

tak myślałem i rozpoznał @ scala.reflect.ScalaSignature adnotacji na klasy. Martwi mnie jednak to, że jest to wyraźne naruszenie enkapsulacji i sprawia, że ​​używanie modyfikatorów dostępu jest zupełnie bezsensowne, o ile można wywoływać cokolwiek z kodu Java. –

+3

Cóż, "bezcelowe" w takim samym stopniu jak modyfikatory dostępu w ogóle są bezcelowe, ponieważ zawsze można ominąć je za pomocą refleksji/wskaźników. – themel

+0

Nie posunąłbym się tak daleko, jak powiedzieć, że można nazwać "coś" z języka Java. Jeśli użyjesz 'apply' jako zwykłego private (w przeciwieństwie do private do' pace'), zobaczysz, że metoda jest rzeczywiście oznaczona jako prywatna w pliku .class. Wynika to z tego, że koncepcja metody prywatnej w scala i java jest dokładnie taka sama, więc kompilator może oznaczyć ją jako prywatną. Z drugiej strony koncepcja metody prywatnej dla pakietu po prostu nie istnieje w java/jvm. –

1

Nie bardzo poprawna odpowiedź 100% ...

Można zrobić obiektu pakiet jeśli chcę zrobić jakiś wymyślnych rzeczy tam z prywatnym klasie. Obiekt pakietu jest dostępny jak każdy inny pakiet. Klasa MyClass jest pakietem prywatnym dla tego obiektu pakietu. Nie jest to jednak pakiet prywatny.

package object com.jasongoodwin.foo { 
    private class MyClass 

    class AnotherClass { 
    val myClass = new MyClass 
    } 
} 
Powiązane problemy