Java Vererbung, Referenzvariable, Sichtbarkeit von Methoden - Frage dazu

Jack159

Lieutenant
Registriert
Dez. 2011
Beiträge
766
Hallo,

gegeben sei folgendes Codebeispiel mit den 3 Klassen:

Code:
public abstract class Lebewesen {

}


public abstract class Tier extends Lebewesen {

}

public class Hund extends Tier {
	
	public void belle() {
		System.out.println("Hund bellt");
	}

}


Dazu jetzt das folgende Beispiel. Die Fragen befinden sich direkt in den Kommentaren:

Code:
public class App {
	
	public static void main(String[] args) {
		
		Lebewesen a = new Hund();
		// a.belle();	Geht nicht, da ja nur die Methoden von Lebewesen.java sichtbar sind
		a = (Hund) a;
		// a.belle();	Wieso ist belle() hier immer noch nicht sichtbar? Ich habe die Rerefenzvariable doch auf Hund gecastet?!
		
	}

}
 
a hat immer noch Typ Lebewesen, daran wird sich nichts ändern

versuchsmal mit Hund b = (Hund) a;
b.belle();
 
Weil "a" immer noch ein "Lebewesen" ist!

Versuche:
Hund b = (Hund) a;
b.belle();

Oder:
((Hund) a).belle();
 
Sondai schrieb:
a hat immer noch Typ Lebewesen, daran wird sich nichts ändern

Das verwirrt mich grad sehr....
Was bewirkt dann denn der folgende Aufruf überhaupt?

Code:
a = (Hund) a;

Ich dachte bisher immer, dass man den Typ der Referenzvariable so eben ändern kann.
 
Stimmt schon, aber du macht quasi wieder
Code:
Lebewesen a = (Hund) a;

Der Typ verändert sich nicht für die Variable durch den Cast, sondern nur auf der rechten Seite ist der Typ Hund bekannt.
Aber wie benneque gesagt hat, würde
Code:
((Hund) a).belle();
funktionieren. Daher musst du eben eine neue Variable mit dem entsprechenden Typ verwenden, welche belle() unterstützt. Und damit bist du eben bei

Code:
Hund b = (Hund) a;
da damit eben der richtige Typ für die Variable b bekannt ist.
 
Jack159 schrieb:
Das verwirrt mich grad sehr....
Was bewirkt dann denn der folgende Aufruf überhaupt?

Code:
a = (Hund) a;

Ich dachte bisher immer, dass man den Typ der Referenzvariable so eben ändern kann.

Laienhaft gesprochen stellst Du damit sicher, dass der Ausdruck auf der rechten Seite vom Typ "Hund" ist. Den Typ der Variablen auf der linken Seite änderst Du damit nicht. Das ist auch nicht möglich.
 
Jack159 schrieb:
Ich dachte bisher immer, dass man den Typ der Referenzvariable so eben ändern kann.

Du verwechselst das vielleicht mit dem Zuweisen von Werten (Bsp.: x = x+1). Typen können Variablen nicht nachträglich zugewiesen werden. Und das ist auch richtig und wichtig.

Überlege dir, welchen Sinn das haben könnte.

Wenn du eine Variable deklarierst, gibst du einen konkreten Typen an und innerhalb des Scopes der Variable hast du die Garantie, dass sich daran nichts ändert. Nun kannst du zurecht einwerfen, dass dies bei Subklassen nicht so schlimm sei, da ja keinerlei Funktionalität wegfalle. Solche Einschränkungen und Regeln sollen den Nutzer der Programmiersprache aber daran hindern Unsinniges zu verfassen. Wenn du so willst ist ein wesentlicher Benefit an der Sache, eben der dass du hier fragst "Warum nicht?". Siehe auch: Typisierung in der Wikipedia.

Tatsächlich gelten Casts als schlechter Stil. Wählst du eine Variable vom Typ Tier, dann willst du dein Objekt auch abstrakt als Tier betrachten. Ein nachträgliches downcasten führt diese Entscheidung ad absurdum. Casts an sich sind eine Aufweichung der Einschränkungen. Sie sollten, wo es nur geht, vermieden werden. In den aller meisten Fällen sind Casts ein Zeichen, dass du dein Design überdenken solltest.
 
Naja, manchmal ist das schon lästig mit den festen Typen. Bsp:

Code:
if(obj instanceof X) {
 X x = (X) obj;
 x.someXMethod();
} else if(obj instanceof Y) {
 Y y = (Y) obj;
 y.someYMethod();
}

klar geht das auch mit ((X) obj).someXMethod(); , aber schön sieht das nicht aus ;)
 
@benneque

Eventuell verstehe ich deinen Einwand hier nicht ganz? :confused_alt:

Dein Code ist doch ein Musterbeispiel für Codesmell. Wenn du dich in dieser Situation befindest, diese Fallunterscheidung machen zu müssen, ja klar, dann brauchst du Casts.

Die Frage ist doch eher wie es dazu kam, dass du gezwungen bist diese Fallunterscheidung einzubauen. Und da muss zuvor irgendwas suboptimales passiert sein.
 
Zurück
Oben