Sie verwenden tatsächlich das Vorlagenmuster. Es gibt zwei Haupt Dinge, die Sie von externen Benutzern zu „verstecken“ Details machen könnte:
1) Verstehen Sie Ihre access modifiers:
Access Levels
Modifier | Class | Package | Subclass | World |
--------------------------------------------------
public | Y | Y | Y | Y |
protected | Y | Y | Y | N |
no modifier | Y | Y | N | N |
private | Y | N | N | N |
Kurz entschlossener Hacker Mobbing ihren Weg in Vergangenheit diesen Schutz mit Reflexion, können diese Achten Sie darauf, dass zufällige Programmierer versehentlich Methoden aufrufen, die ihnen am besten verborgen bleiben. Die Programmierer werden dies zu schätzen wissen. Niemand möchte eine überladene API verwenden.
Derzeit b.doWork()
ist protected
. So wäre es nur in Ihrem main()
sichtbar, wenn Ihr main()
in Klasse A
(ist es nicht), Unterklasse B
(ist es nicht), oder in dem gleichen Paket (nicht klar, Sie haben keine Hinweise über das Paket (s) posten Ihr Code befindet sich in).
Dies wirft die Frage auf, wen Sie vor dem Sehen schützen möchten? Wenn das von Ihnen erstellte Paket nur von Ihnen entwickelt wird, ist es möglicherweise nicht so schlimm. Wenn viele Leute in diesem Paket mit vielen anderen Klassen herumstampfen, ist es unwahrscheinlich, dass sie mit den Klassen A
und B
vertraut sind. Dies ist der Fall, wenn Sie nicht wollen, dass alles rumhängt, wo es jeder sehen kann. Hier wäre es schön, nur Klassen- und Unterklassenzugriff zu erlauben. Aber es gibt keinen Modifikator, der den Zugriff auf Unterklassen ermöglicht, ohne auch den Paketzugang zuzulassen. Solange Sie Unterklasse protected
sind, ist das Beste, was Sie tun können. In diesem Sinne sollten Sie keine Pakete mit einer großen Anzahl von Klassen erstellen. Halten Sie Pakete fest und fokussiert. Auf diese Weise werden die meisten Leute außerhalb des Pakets arbeiten, wo die Dinge schön und einfach aussehen.
Kurz gesagt, wenn Sie sehen möchten, main()
verhindert, rufen Sie main()
in einem anderen Paket.
package some.other.package
public final class Main {
...
}
2) Der Wert dieses nächsten Ratschlag wird schwer sein, mit Ihrem aktuellen Code zu verstehen, denn es geht um die Lösung von Problemen ist, die nur kommen wird, wenn Ihr Code auf erweitert. Aber es ist wirklich eng mit der Idee von Menschen aus den Dingen zu sehen, wie b.doWork()
What does "program to interfaces, not implementations" mean?
in Ihrem Code zu schützen, was das bedeutet, ist es besser wäre, wenn Haupt sieht wie folgt aus:
public static void main(String[] args) {
A someALikeThingy = new B(); // <-- note use of type A
someALikeThingy.work(); //The name is silly but shows we've forgotten about B
//and know it isn't really just an A :)
}
Warum? Was macht die Verwendung des Typs A
im Vergleich zum Typ B
von Bedeutung? Nun A
ist näher an eine Schnittstelle. Beachten Sie, hier meine ich nicht nur, was Sie bekommen, wenn Sie das Schlüsselwort interface
verwenden.Ich meine Typ B
ist eine konkrete Implementierung des Typs A
und wenn ich nicht absolut Code gegen B
schreiben muss, würde ich wirklich lieber nicht, weil wer weiß, was komisch nicht A
Dinge B
hat. Dies ist hier schwer zu verstehen, da der Code in main kurz ist & süß. Auch die öffentlichen SchnittstellenA
und B
sind nicht so unterschiedlich. Sie haben beide nur eine öffentliche Methode work()
. Stellen Sie sich vor, dass main()
lang und gewunden war, Imagine B
hatte alle Arten von nicht A
Methoden hängen davon ab. Stellen Sie sich nun vor, Sie müssen eine Klasse C
erstellen, mit der Sie hauptsächlich arbeiten möchten. Wäre es nicht beruhigend zu sehen, dass während der Hauptleitung eine B
, dass so weit wie jede Zeile in der Hauptsache, dass B
ist nur einige einfache A
wie etwas gefüttert wurde. Außer für den Teil nach der new
könnte dies wahr sein und Sie davor bewahren, irgendetwas zu tun main()
, aber das new
zu aktualisieren. Ist das nicht der Grund, warum eine stark typisierte Sprache manchmal schön sein kann?
<rant>
Wenn Sie denken auch, dass ein Teil nach new
mit dem B()
ist zu viel Arbeit zu aktualisieren Sie nicht allein sind. Diese besondere kleine Obsession hat uns dazu gebracht, die dependency injection movement, die eine Reihe von Frameworks, die wirklich mehr über die Automatisierung der Objektkonstruktion als eine einfache Injektion, dass jeder Konstruktor Sie tun können, war hervorgebracht.
</rant >
Update:
ich Ihre Kommentare sehen, die Sie zögern, kleinen engen Pakete zu erstellen. Ziehen Sie in diesem Fall in Erwägung, ein vererbungsbasiertes Vorlagenmuster zugunsten eines zusammensetzungsbasierten Strategie-Patterns aufzugeben. Sie bekommen immer noch Polymorphie. Es passiert einfach nicht umsonst. Etwas mehr Code schreiben und Indirection. Aber Sie können den Status sogar zur Laufzeit ändern.
Dies scheint kontraintuitiv zu sein, denn jetzt muss doWork()
öffentlich sein. Was für ein Schutz ist das? Nun können Sie B
ganz hinter oder sogar innerhalb AHandler
verstecken. Dies ist eine menschenfreundliche Fassadenklasse, die den ursprünglichen Vorlagencode enthält, aber nur work()
darstellt. A
kann nur ein interface
sein, so dass die AHandler
immer noch nicht weiß, dass es eine B
hat. Dieser Ansatz ist bei der Abhängigkeitsinjektionsmenge beliebt, hat jedoch sicherlich keine universelle Anziehungskraft. Manche tun es jedes Mal blind, was viele ärgert. Hier können Sie mehr darüber lesen: Prefer composition over inheritance?
"ein leicht in der Lage ist, aus Versehen b.doWork nennen()". "Ja wirklich?" Es ist geschützt, also können nur A- oder B-Instanzen es anrufen. –
Leider, da es geschützt ist, können alle Klassen aus dem Paket es nennen. Pakete zu splitten ist ein Weg zu gehen, obwohl ich eher vermeiden möchte, 1- oder 2-Klasse-Pakete zu haben. –
Nein! Sie beschreiben den Standardzugriffsmodifikator (d. H. Keiner). Protected bedeutet "nur ich oder Klassen, die mich erweitern können diese verwenden" –