Java Methoden aus anderen Unterklassen aufrufen (Greenfoot)?

2 Antworten

Vom Beitragsersteller als hilfreich ausgezeichnet

Da du die Objekte in einem PickableObjects-Array speicherst werden die Objekte auch nur als PickableObjects behandelt, hier wird implizit ein Upcast durchgeführt wobei die zusätzlichen Funktionalitäten der Unterklasse verloren gehen.

Du kannst aber zur Laufzeit wieder einen Downcast durchführen wenn du dir sicher bist dass es sich bei dem Objekt um ein Objekt der speziellen Unterklasse handelt um die Funktionalität der Unterklasse wieder herzustellen.


MoonSpirit 
Beitragsersteller
 12.03.2020, 15:23

Okay, Danke erstmal für deine Antwort! Könntest du mir vielleicht noch kurz sagen wie man diesen "umgedrehten super-Befehl" benutzt?

LG und Danke!

Myrmiron  12.03.2020, 15:32
@MoonSpirit

Durch einen Downcast versicherst du dem Compiler (und dem Programm) dass es sich bei dem Objekt auch ganz sicher um das Objekt der Unterklasse handelt.

Beispiel:

Ball konkreterBall = new Ball();
PickableObject x = konkreterBall; -> Funktioniert da jeder Ball auch ein PickableObject ist!

konkreterBall.methodeDieNurDieBallklasseKann(); -> Klappt!

x.methodeDieNurDieBallklasseKann(); -> Fehler da der Ball für das Programm gerade wie ein PickableObject aussieht!

((Ball)x).methodeDieNurDieBallklasseKann(); -> Hier wird durch einen Downcast dem Programm versichert dass es sich bei x um einen Ball handel, klappt also wieder!

mertkert  12.03.2020, 15:35
@MoonSpirit

Hier mit Downcasts herumzufuhrwerken ist eher keine gute Idee. Code dieser Sorte ist zwar manchmal unvermeidlich, aber für derartig einfache Programme ein deutliches Alarmzeichen für schlechten Entwurf:

Superclass bla = ...

if(bla instanceof Subclass1) {
   ((Subclass1)bla).doSomething();
} else if (bla instanceof Subclass2) ...

Wenn doSomething() für jedes PickableObject sinnvoll ist, sollte es auch Teil von dessen Interface sein. Jede Subklasse kann es dann nach Bedarf passend implementieren, zur Laufzeit wird der richtige Code ausgeführt.

Wenn ich "public void doSomething" in der Klasse PickableObjects definiere passiert etwas, wenn ich es hingegen nur in den Carnot, PickAxe... definiere erkennt er die Methode nicht

Das ist auch logisch so. Wenn doSomething() für alle PickableObjects sinnvoll ist, dann definiere es da drin (ggf. leer oder abstract). In den Subklassen (Apple, Ball) wird es dann implementiert bzw. überschrieben.


MoonSpirit 
Beitragsersteller
 12.03.2020, 15:53

jup, nur möchte ich das die "doSomething()" Methode sich selbst zurückgibt.

z.B. soll er nach dem Aufruf dieser Methode dem Spieler 10 Leben zurückgeben, oder sich mit einer bestimmten Wahrscheinlichkeit in etwas anderes verwandeln. um eben dieses "return this" zurückzugeben und das ganze ordentlich zu halten würde ich die Methode gerne in der jeweiligen Klasse definieren.

LG und danke!

mertkert  12.03.2020, 16:04
@MoonSpirit

Ich bin nicht sicher, ob ich dich verstehe.

Das doSomething() soll also ein PickableObject zurückgeben, ggf. auch sich selbst? Das kann es ja ohnehin.

Du musst grob gesagt drei Dinge unterscheiden: Interface, Implementierung, und Daten (des Objekts zur Laufzeit).

Deine Subklassen erben zwingend das Interface der Superklasse. Sie erben auch die Implementierungen, können diese aber überschreiben (also durch eigene ersetzen). Zur Laufzeit werden natürlich immer die Daten des jeweiligen Objekts genommen (wenn wir jetzt mal keine statischen Instanzvariablen verwenden).

Wenn sich hinter einem PickableObject also tatsächlich zur Laufzeit eine PickAxe versteckt, wird automatisch deren Implementierung von doSomething() aufgerufen und natürlich mit den Daten des jeweiligen PickAxe-Objekts. Der Aufrufer muss sich nicht darum kümmern.