Ich verstehe die Idee des Paketumfangs und habe manchmal sogar gedacht, dass ich es wollte. Jedes Mal, wenn ich mich mit der ernsthaften Absicht auf den Weg machte, es zu versuchen, stellte ich fest, dass es nicht den Anforderungen entsprach, von denen ich dachte, dass es dienen würde.
Mein Hauptproblem scheint immer zu sein, dass die Dinge, deren Umfang ich einschränken möchte, niemals im selben Paket enthalten sind. Sie können konzeptionell alle miteinander verknüpft sein, aber die logische Aufteilung der Daten innerhalb der Anwendung hat sie als separate untergeordnete Pakete eines größeren Pakets.
Zum Beispiel kann ich ein Missionsmodell haben und ich möchte, dass nur andere Missionswerkzeuge, wie meine missionServices, einige Methoden verwenden. Am Ende habe ich jedoch Missions.models und Missions.services als meine Pakete, sodass MissionModel und MissionService nicht denselben Paketumfang haben. Es scheint nie eine Situation zu geben, in der Pakete die Dinge angemessen enthalten, für die ich erhöhte Berechtigungen haben möchte, ohne auch zahlreiche Dinge zu enthalten, für die ich diese Berechtigungen nicht haben möchte. und selten habe ich das Gefühl, dass der Vorteil des Paketumfangs eine Methode rechtfertigt, die meine Projektarchitektur so ändert, dass alles im selben Paket platziert wird. Oft erweisen sich entweder Aspekte oder eine Art Umkehrung der Kontrolle als der bessere Ansatz für jedes Problem, für das ich kurz über das Scoping von Paketen nachgedacht habe.
Ich bin eher neugierig, dass dies allgemein von allen Java-Entwicklern als wahr angesehen wird oder nur ein Zufall meiner Arbeit ist. Wird der Paketumfang in der realen Welt häufig genutzt? Gibt es viele Fälle, in denen die Verwendung als gute Form angesehen wird, oder wird sie meist als altes Verhalten angesehen, das in der modernen Entwicklung selten ausgenutzt wird?
Ich frage nichts darüber, warum der private Bereich des Pakets standardmäßig ist. Ich frage, wann es unabhängig von den Standardeinstellungen verwendet werden soll. Die meisten Diskussionen darüber, warum es sich um eine Standardeinstellung handelt, werden nicht wirklich behandelt, wenn der Paketumfang tatsächlich nützlich ist. Stattdessen wird lediglich argumentiert, warum die beiden anderen häufig verwendeten Bereiche nicht standardmäßig sein sollten, damit das Paket durch Eliminierung gewinnt. Außerdem geht es bei meiner Frage um den aktuellen Entwicklungsstand. Insbesondere haben wir uns so weit entwickelt, dass andere Tools und Paradigmen den Umfang des Pakets weniger nützlich machen als damals, als die Entscheidung, es als Standard festzulegen, Sinn machte.
java.util.String
und anjava.util.Integer
.Antworten:
Im gesamten
java.util.*
Paket gibt es Fälle, in denen Code mit Schutz auf Paketebene geschrieben wird. Zum Beispiel dieses Bitjava.util.String
- ein Konstruktor in Java 6 :oder diese getChars-Methode :
Der Grund dafür ist, dass die Entwickler des Codes (und
java.util.*
als eine ziemlich große Bibliothek betrachtet werden können) die Möglichkeit einer schnelleren Leistung auf Kosten eines Verlusts verschiedener Sicherheit (Bereichsüberprüfungen von Arrays, direkter Zugriff auf andere Felder) wünschten Dies impliziert eher die Implementierung als die Schnittstelle ("unsicherer" Zugriff auf Teile der Klasse, die ansonsten über öffentliche Methoden als unveränderlich angesehen werden).Durch die Einschränkung, dass auf diese Methoden und Felder nur andere Klassen im
java.util
Paket zugreifen können, wird eine engere Kopplung zwischen ihnen hergestellt, aber auch vermieden, dass diese Implementierungsdetails der Welt zugänglich gemacht werden .Wenn Sie an einer Anwendung arbeiten und sich nicht um andere Benutzer kümmern müssen, müssen Sie sich keine Sorgen um den Schutz auf Paketebene machen. Abgesehen von verschiedenen Aspekten der Designreinheit könnten Sie alles machen
public
und damit einverstanden sein.Wenn Sie jedoch an einer Bibliothek arbeiten, die von anderen verwendet werden soll (oder vermeiden möchten, dass Ihre Klassen für ein späteres Refactoring zu stark verwickelt werden), sollten Sie das strengste Schutzniveau verwenden, das Ihnen für Ihre Anforderungen gewährt wird. Oft bedeutet dies
private
. Manchmal müssen Sie jedoch ein wenig der Implementierungsdetails anderen Klassen im selben Paket zur Verfügung stellen, um Wiederholungen zu vermeiden oder die eigentliche Implementierung auf Kosten der Kopplung der beiden Klassen und ihrer Implementierungen etwas zu vereinfachen. Somit ist der Schutz auf Paketebene.quelle
Integer.toString()
undString.valueOf(int)
können Code freigeben, ohne ihn der Welt auszusetzen. Diejava.util
Klassen sollen zusammenarbeiten, um eine größere Gesamtheit von Funktionen bereitzustellen, anstatt einzelne Klassen zu sein, die vollständig Inseln für sich sind - sie sind zusammen in einem Paket und teilen die Implementierungsfunktionen über das Scoping auf Paketebene.Manchmal eskaliere ich die Sichtbarkeit privater oder geschützter Methoden zum Paket, damit ein Junit-Test auf einige Implementierungsdetails zugreifen kann, auf die von außen nicht zugegriffen werden sollte.
Da der Junit-Test dasselbe Paket wie der zu testende Artikel enthält, kann er auf diese Implementierungsdetails zugreifen
Beispiel
Es ist fraglich, ob dies eine "gute" Verwendung ist oder nicht, aber es ist pragmatisch
quelle
protected
zum Paketumfang aufsteigen? liefertprotected
bereits Paketzugriff. Es ist ein bisschen seltsam, aber ich denke, sie wollten keine zusammengesetzten Bereichsdeklarationen wieprotected packagescope void doSomething()
(für die auch ein neues Schlüsselwort erforderlich ist) benötigen.Es ist nicht besonders nützlich, insbesondere als Standard, in einer Welt, in der Menschen dazu neigen, die gepunkteten Namen von Paketen so zu verwenden, als wären sie Unterpakete. Da Java kein Unterpaket hat, hat xyinternals nicht mehr Zugriff auf xy als auf ab. Paketnamen sind entweder gleich oder unterschiedlich. Eine teilweise Übereinstimmung unterscheidet sich nicht davon, nichts gemeinsam zu haben.
Ich denke, die ursprünglichen Entwickler hätten nie erwartet, dass diese Konvention verwendet wird, und wollten die Dinge einfach halten, ohne die Komplexität hierarchischer Pakete im Ada-Stil zu erhöhen.
Java 9 behebt dies, indem Sie mehrere Pakete in ein Modul einfügen und nur einige exportieren können. Dadurch wird der Paketumfang jedoch noch redundanter.
In einer idealen Welt würden sie den Standardbereich in "Modulbereich, wenn ein enthaltendes Modul vorhanden ist, andernfalls Paketbereich" ändern. Anschließend können Sie die Implementierung innerhalb eines Moduls freigeben und so das Refactoring ermöglichen, ohne die exportierten Schnittstellen zu beschädigen. Aber vielleicht gibt es eine gewisse Subtilität, warum dies die Abwärtskompatibilität beeinträchtigen oder auf andere Weise schlecht sein würde.
quelle
Die Art der Kohäsion, die Sie beschreiben, ist nicht wirklich das beste Beispiel dafür, wo Sie den Paketzugriff verwenden würden. Das Paket ist praktisch zum Erstellen von Komponenten, Modulen, die auf einer Schnittstelle austauschbar sind.
Hier ist ein grobes Beispiel eines Szenarios. Angenommen, Ihr Code wurde neu organisiert, um den funktionalen Zusammenhalt und die Komponentisierung zu verbessern. Vielleicht 3 Gläser wie:
Durch die Verwendung der Paketebene in Mission5000.java können Sie sicher sein, dass kein anderes Paket oder keine andere Komponente wie der MissionManager eng mit der Implementierung der Mission verbunden werden kann. Dies ist nur die von "M co" bereitgestellte Komponente von "M co", die tatsächlich eine eigene spezielle Markenimplementierung einer Mission erstellt. Der Mission Manager muss MissionBuiler.createMission (...) aufrufen und die definierte Schnittstelle verwenden.
Auf diese Weise wissen wir, dass die Implementierer von MissionManager.jar die API nicht umgangen haben und die Implementierung von MCo direkt verwenden, wenn die Mission-Implementierungskomponente ersetzt wird.
Daher können wir MCo-missionizer5000.jar gegen ein Konkurrenzprodukt austauschen. (Oder vielleicht ein Mock zum Testen des Missionsmanagers)
Umgekehrt kann MCo einiges tun, um die Geschäftsgeheimnisse seiner eigenen Missionare zu verbergen.
(Dies hängt damit zusammen, dass Instabilitäts- und Abstraktheitsideen auch in Komponenten durchgesetzt werden.)
quelle
Da der Paketumfang in Java nicht hierarchisch gestaltet ist, ist er kaum nützlich. Wir verwenden den Paketbereich überhaupt nicht und definieren alle Klassen als öffentlich.
Stattdessen verwenden wir unsere eigenen Zugriffsregeln, die auf der Pakethierarchie und den vordefinierten Paketnamen basieren.
Wenn Sie an Details interessiert sind, suchen Sie bei Google nach "CODERU-Regeln".
quelle