Subklasse: abstrakte Methode implementieren und privatisieren
-
Hallo,
ich habe folgende Situation:
Eine abstrakte Basisklasse, die eine abstrakte Methode deklariert, die von der erbenden Subklasse definiert werden soll.
Doch soll diese Methode von nun an privat sein, das heißt eine weitere Subklasse, die die oben genannte Subklasse erweitert, darf die Methode nicht mehr sehen.
Wie kann ich das mit Java Sprachmitteln realisieren?
Vielen Dank schonmal
Gruß,
Tim
-
wenn ich dich richtig verstanden habe ist das ein weg:
abstract class AbstractBase { abstract void foo(); } class AbstractSub extends AbstractBase { @Override final void foo() { } } class AbstractSub2 extends AbstractSub { @Override void foo() // error, darf nicht mehr überschrieben werden { } }
-
xindon schrieb:
Doch soll diese Methode von nun an privat sein, das heißt eine weitere Subklasse, die die oben genannte Subklasse erweitert, darf die Methode nicht mehr sehen.
Die Frage ist, ob dieses Vorgehen überhaupt sinnvoll ist. In Java gibts ja nicht sowas wie private Vererbung, somit kann man ein Objekt immer in den Basisklassentypen konvertieren. Folglich wäre es jederzeit möglich, über die Referenz der Basisklasse doch noch die Methode aufzurufen, selbst wenn diese zwischendurch privat gemacht werden könnte.
abstract class AbstractBase { public abstract void foo(); } class Base extends AbstractBase { // nehmen wir an, wir könnten foo() tatsächlich privat machen. private void foo() { // ... } } // Abgeleitete Klasse: soll foo() nicht mehr sehen. class Derived extends Base { void accessFoo() { // Geht nicht, da privat. Alles okay soweit. foo(); // Geht aber über Basisklassen-Umweg. // AbstractBase.foo() ist schliesslich public. AbstractBase hacker = this; hacker.foo(); } }
Die Frage ist also eher, durch welches Design du dich zu so einem Schritt gezwungen fühlst.
-
xindon schrieb:
Hallo,
ich habe folgende Situation:
Eine abstrakte Basisklasse, die eine abstrakte Methode deklariert, die von der erbenden Subklasse definiert werden soll.
Doch soll diese Methode von nun an privat sein, das heißt eine weitere Subklasse, die die oben genannte Subklasse erweitert, darf die Methode nicht mehr sehen.
Wie kann ich das mit Java Sprachmitteln realisieren?
Vielen Dank schonmal
Gruß,
TimGarnicht und geht auch in keine andere Sprache. Wenn du eine Basisklasse die Methoden deklariert, muss man diese Implementieren mit ihren Schutzattribute.
-
Nexus schrieb:
Folglich wäre es jederzeit möglich, über die Referenz der Basisklasse doch noch die Methode aufzurufen, selbst wenn diese zwischendurch privat gemacht werden könnte.
Das ist ein sehr guter Punkt!
Nexus schrieb:
Die Frage ist also eher, durch welches Design du dich zu so einem Schritt gezwungen fühlst.
Die Situation ist wie folgt (es handelt sich um eine kleine 3D-Engine):
Die abstrakte Klasse Application, die das Grundgerüst der Anwendungen, die meine Engine benutzen wollen, darstellt.Davon eine abstrakte Subklasse LWJGLApplication, die bestimmte Methoden von Application überschreibt und eben in LWJGL implementiert.
Um jetzt eine Anwendung zu erstellen, die meine Engine mit LWJGL benutzt, muss lediglich LWJGLApplication erweitert werden.
Das sieht dann so aus: http://pastebin.com/m6a515499Jetzt definiert die abstrakte Basisklasse einige Methoden, die zwar von LWJGLApplication implementiert werden müssen, aber in der Subsubklasse vom Anwender unbedingt unsichtbar sein müssen. (zB destroyLibrary(), was Application aufruft und von LWJGLApplication implementiert wird).
Hab aber auch schon eine Idee, wie ich's umstrukturieren werde
Trotzdem vielen Dank für die Hilfe!
-
Du willst die meistens Methode von LWJGLApplication eher protected haben, oder?
-
Zeus schrieb:
Du willst die meistens Methode von LWJGLApplication eher protected haben, oder?
Als Beispiel betrachte ich die oben erwähnte libraryDestroy().
Die Methode ist als protected abstract deklariert in der abstrakten Application Klasse. LWJGLApplication erweitert die Klasse und implementiert die Methode libraryDestroy() mit dem üblichen Aufräum-Code von LWJGL.
Die abstrakte Basisklasse Application besitzt nun die Methode start(), die die Initialisierungsmethoden aufruft, die Hauptschleife startet und am Ende eben libraryDestroy() aufruft.
Das Problem ist jetzt aber: Die vom Nutzer implementierte Subklasse von LWJGLApplication hat auch Zugriff auf libraryDestroy() und kann somit das ganze Programm abschießen.
Aber wie gesagt, dieses Design habe ich schon wieder verworfen und es stattdessen über ein paar Interfaces und ohne Vererbung realisiert.
-
xindon schrieb:
Das Problem ist jetzt aber: Die vom Nutzer implementierte Subklasse von LWJGLApplication hat auch Zugriff auf libraryDestroy() und kann somit das ganze Programm abschießen.
Und wo soll hier das Problem sein? Wenn ich von LWJGLApplication erbe, dann ist meine Klasse auch eine LWJGLApplication. Das mache ich, wenn ich LWJGLApplication erweitern will um z.B. mit einer anderen Library umzugehen. Dann muss ich sogar libraryDestroy() überschreiben, wo soll ich den sonst meine Libs wieder aufräumen.
Der OOP-Weg ist hier die Klasse LWJGLApplication so zu implementieren, dass man sie als Komposition verwenden kann und man sie nicht zu erweitern braucht. Also statt
class MyApp extends LWJGLApplication { }
besser
class MyApp { private LWJGLApplication app; }
Das ist das gleiche Problem den man in vielen Java Beispielprogrammen sieht. Anstatt von JFrame abzuleiten, sollte man lieber Komposition verwenden. Schlecht:
class MyFrame extends JFrame { }
Besser:
class MyFrame { private JFrame frame; }
Komposition immer der Verwebung vorziehen und dann stellt sich dein Problem erst gar nicht.
-
Noch mal eine Frage zu Komposition.
Welches Komposition meinst du? Das Design-Pattern oder die "Verbindung" in UML?
Meinst du das zweite?
-
Letzteres. Geht auch aus den vorherigen Posts hervor.