2012-10-09 2 views
17

Sorry für den eingängigen Titel. ;-)kann ich keine Paket-Privat-Klasse in Scala hazeln?

Ich möchte ein Paket-private-Klasse mit einem Paket-private Methode in Scala schaffen, so dass meine Klasse sieht etwas wie folgt aus:

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 
} 

Wenn ich jedoch javap verwenden, um zu überprüfen, was die Scala-Compiler erzeugt effektiv, ich so etwas wie dieses:

$ 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); 
    ... 
} 

das bedeutet, dass, obwohl die Scala-Compiler könnte die Zugangsbeschränkungen respektieren, habe ich noch diese Klasse von jedem Java-Code aufrufen könnte, was eine klare Verletzung Einkapselung ist.

Fehle ich etwas? Gibt es eine Möglichkeit, dies wie vorgesehen zu machen?

+2

+1 für lustigen Titel –

Antwort

15

Neben @ Régis' Antwort, ist der Grund, Scala-Compiler nicht die Klasse Paket-private machen da ist von Scala es Regeln kann aus anderen Paketen zugegriffen werden: nämlich Subpackages von net.java.truevfs.ext.pace. Z.B.

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

class Subclass extends AspectController { ... } 

ist legal in Scala, aber in Java-Klassen aus net.java.truevfs.ext.pace.subpackage nicht Paket-privaten Klassen von net.java.truevfs.ext.pace zugreifen.

+0

+1. Ich wollte das gleiche zeigen. –

+0

Guter Punkt - ich wusste das nicht. –

+0

Nun, das bedeutet tatsächlich, dass das Konzept einer package-private Klasse in Scala gar nicht existiert. Schade, denn für mich war es ein primäres Element meines Java-Toolsets, um die Kapselung zu fördern (ich verstehe, dass dieser Schutz sowieso nur auf der Sprachebene funktioniert). –

9

Sie verpassen nichts. Viele der Zugriffsbeschränkungen in scala haben weder in Java noch auf der Ebene jvm ein Äquivalent. Die zusätzlichen Informationen befinden sich offensichtlich genau dort in der .class-Datei, aber gibt es als benutzerdefinierte Anmerkungen, die nur der Scala-Compiler interpretieren wird. Das Scala-Objektmodell kann nur teilweise mit dem jvm-Objektmodell abgeglichen werden, und ein Java-Compiler wird nur dieses Teilmodell sehen. Ich würde sagen, dass die Übereinstimmung ziemlich nahe ist und der Scala-Compiler eine sehr gute Arbeit bei der Java-Interoperabilität leistet, aber nichts ist perfekt.

+0

Ich dachte so und die @ scala.reflect.ScalaSignature Anmerkung auf der Klasse anerkannt. Was mich jedoch beunruhigt ist, dass dies eine klare Verletzung der Kapselung ist und die Verwendung von Zugriffsmodifizierern völlig sinnlos macht, solange Sie alles aus Java-Code aufrufen können. –

+3

Nun, "sinnlos" in dem gleichen Maße, dass Zugriffsmodifikatoren im Allgemeinen sinnlos sind, da Sie sie immer über Reflektion/Zeiger umgehen können. – themel

+0

Ich würde nicht so weit gehen zu sagen, dass man "alles" von Java aufrufen kann. Wenn Sie "apply" plain private (im Gegensatz zu privat für "pace") wählen, werden Sie feststellen, dass die Methode in der .class-Datei tatsächlich als privat markiert ist. Dies liegt daran, dass das Konzept einer privaten Methode in scala und in java genau gleich ist, sodass der Compiler sie als privat markieren kann. Andererseits gibt es in java/the jvm das Konzept einer zu einem Paket privaten Methode einfach nicht. –

1

Nicht wirklich eine 100% richtige Antwort ...

Sie können ein Paket Objekt machen, wenn ich mit einem privaten Klasse dort einige ausgefallene Sachen machen wollen. Auf das Paketobjekt wird wie bei jedem anderen Paket zugegriffen. Die Klasse MyClass ist das Paket privat für dieses Paketobjekt. Es ist jedoch nicht Paket privat.

package object com.jasongoodwin.foo { 
    private class MyClass 

    class AnotherClass { 
    val myClass = new MyClass 
    } 
} 
Verwandte Themen