Instanz einer Subklasse anhand deren Superklasse

Diluvian

Mitglied
Hallo zusammen,
Ich bin mir leider nichtmal sicher ob ich nun die Frage richtig stelle. Es ist folgender Fall gegeben:

Java:
SuperKlasse object = new SubKlasse();

Wieso macht man das? Wenn man die Thematik beigebracht bekommt (Bücher, Online), sieht man die für mich aktuell noch logischere Variante:

Java:
SubKlasse object = new SubKlasse();

Ich hab nun eine Weile gesucht :rtfm: und leider keine Antwort darauf gefunden. Vielen Dank euch also schonmal für die Hilfe!
 
Weil man so seinen Code flexibler/dynamischer gestalten kann. Man weiß nicht immer bereits während des Programmierens, welche Typen letzten Endes wirklich benutzt werden.

Vielleicht mal ein paar Beispiele aus Übungsprojekten von mir:
Java:
class Operation{}

class Addition extends Operation{}

class Subtraction extends Operation{}

public static Operation getOperation(String sign){
    	
    	Operation searched = null;
    	switch(sign){
    		case "+":
    			searched = new Addition();
    			break;
    		case "-":
    			searched = new Subtraction();
    			break;
                [...]
    	}
    	
    	return searched;
    }



oder :

Java:
public class Service
{	
	private BaseDao dao;

       public Service(BaseDao dao){
             this.dao = dao;
       }    
}

class BaseDao{}

class UserDao extends BaseDao{}
Dao = greift direkt auf die Datenbank zu

Ich weiß hier während des Programmierens nur, dass mein Service mal irgendeine Form von Dao brauchen wird, kann/möchte mich aber noch nicht so genau festlegen, welcher Dao es mal wird. Die Alternative hierzu wäre, für jeden potentiellen Dao einen eigenen Konstruktor zu generieren, was bei 2-3 Kandidaten noch machbar ist, aber bei mehr ganz schnell lästig wird.


Man versucht, Code so allgemein wie möglich, aber so spezifisch wie notwendig zu schreiben. Indem du dich nicht genau festlegst, lässt du dir mehr Optionen offen und das Risiko sinkt, dass du bei späteren Ergänzungen erneut zig Klassen anfassen musst.
Besonders bei der Definition von Interfaces ist das relevant.


Oder Beispiel ausm echten Leben:
"Mir egal, was es gibt, Hauptsache Pizza!"
;-)
 
Hier auch ein gutes Beispiel:
Du hast 5 Objekte. "Boot", "Motorrad", "Auto", "LKW", "Flugzeug". Nun hat jedes dieser Objekte einen spezifischen Preis. Jetzt will man eine unbestimmte Anzahl von diesen Objekten mit einer Funktion:
Java:
public float kaufen(Boot[] boote, Motorrad[] motorräder, Auto[] autos, LKW[] lkws, Flugzeug[] flugzeuge){
float preis;
for(Boot b:boote){
preis+=b.getPreis();
}
for(Motorrad m:motorräder){
preis+=m.getPreis();
}
for(Auto a:autos){
preis+=a.getPreis();
}
for(LKW l:lkws){
preis+=l.getPreis();
}
for(Flugzeug f:flugzeuge){
preis+=f.getPreis();
}
return preis;
}

Wie man sieht ist die ganze Methode seeeeehr aufgebläht. Und jetzt kommt die Vererbung ins Spiel:
Jetzt haben wir noch eine Klasse "Fahrzeug" und lassen alle unsere Objekte davon erben. In diese Klasse Fahrzeug geben wir jetzt noch unsere getPreis Funktion. Jetzt sind alle unsere Objekte Fahrzeuge, und jedes Fahrzeug hat laut unserer Definition einen Preis welchen wir abfragen können. Nun können wir die Funktion deutlich vereinfachen:
Java:
public float kaufen(Fahrzeug[] fahrzeuge){
float preis;
for(Fahrzeug f:fahrzeuge){
preis+=f.getPreis;
}
return preis;
}

Hast jetzt den Anwendungszweck anhand des Beispieles verstanden 🙂?
 
Vielen dank für eure Ausführliche Erklärung, das hat mir sehr geholfen! Einen Nachteil sehe ich aktuell jedoch (zumindest bis jetzt): Man muss auf diesem Wege immer mit Downcasts arbeiten, wenn man auf spezielle Methoden der Subklasse zugreifen möchte. Kann das nicht verwirrend sein? Selbst wenn ich vorher "instanceof" abfrage, würde er bei dem Instanz vom Typ der Superklasse sowie bei der Subklasse "true" zurück werfen und ich wüsste nicht, ob ich nun ein Instanzobjekt von der Superklasse oder der Subklasse vor mir habe (klar, meine programmierumgebung würde mir dabei unter die Arme greifen).

Generell habe ich es aber verstanden. Wirklich sehr vielen Dank!
 
Vielen dank für eure Ausführliche Erklärung, das hat mir sehr geholfen! Einen Nachteil sehe ich aktuell jedoch (zumindest bis jetzt): Man muss auf diesem Wege immer mit Downcasts arbeiten, wenn man auf spezielle Methoden der Subklasse zugreifen möchte. Kann das nicht verwirrend sein?
Du hast vollkommen Recht, dass man einen Downcast braucht, um spezielle Methoden der Unterklasse abzufragen. Der Sinn einer Vererbungshierarchie ist ja aber gerade, so viele Gemeinsamkeiten wie möglich zusammenzufassen. Dementsprechend sollten solche Downcasts eher die Ausnahme, als die Regel sein.


Selbst wenn ich vorher "instanceof" abfrage, würde er bei dem Instanz vom Typ der Superklasse sowie bei der Subklasse "true" zurück werfen und ich wüsste nicht, ob ich nun ein Instanzobjekt von der Superklasse oder der Subklasse vor mir habe (klar, meine programmierumgebung würde mir dabei unter die Arme greifen).


Java:
class Animal{
 
    void move(){}  
}

class Cat extends Animal{

  void meow(){}

}

class Dog extends Animal{

  void bark(){}

}

                Animal a = new Animal();
                Animal c = new Cat();
		Animal d = new Dog();
		
                System.out.println(a instanceof Animal); //true
		System.out.println(a instanceof Cat); //false

		System.out.println(c instanceof Cat); //true
		System.out.println(c instanceof Animal); //true
		
		System.out.println(d instanceof Dog); //true
		System.out.println(d instanceof Cat); //false

Du kannst mit instanceof differenzieren zwischen Dog- und Cat-Objekten und somit dein Objekt x explizit casten und damit auf die spezifischen Methoden zugreifen.
"Cat" hat sowieso alle Methoden der Animal-Klasse, also ist es mir ziemlich Schnuppe, ob beim Aufruf von c.move() die Methode eine "eigene" ist oder von Animal geerbt wurde. Wenn Cat eine spezielle move-Implementierung benötigt, überschreibe ich diese Methode einfach in der Cat-Klasse.
 
Das mit dem Methoden-Überschreiben weiß ich, mir war nur nicht bewusst, dass instanceof so differenziert. Vielen dank dafür. Meine Fragen sind damit aktuell alle geklärt 🙂.

Grüße!
 

Zurück
Oben