Vorlesung Informatik 1 - Teil A: Java Kurs
2.10 Zuweisungskompatibilität, Polymorphie
Obwohl wir von abstrakten Klassen oder mehr noch von einem Interface keine Objekte erzeugen können, kann man Variablen davon definieren.
Wir verwenden das z.B. in unserer Klasse SpielfFgur:
public class SpielFigur extends Rectangle2D.Double implements MouseListener, MouseMotionListener
{
...
protected Spiel spiel;
public SpielFigur(double xC, double
yC, double breite, double hoehe, Spiel spiel) {
super(xC-breite/2, yC-hoehe/2, breite, hoehe);
this.spiel = spiel;
Die Klasse Spiel ist abstrakt, kann also nicht instanziiert werden - man kann keine Objekte vom Typ Spiel erzeugen. Trotzdem gibt es eine Instanz- und eine lokale Variable, die offensichtlich auf Objekte dieses Typs zeigen??
Dieser scheinbare Widerspruch löst sich wie folgt auf:
Variablen vom Typ einer Basisklasse oder vom Typ eines Interface können auf
Objekte abgeleiteter bzw. implementierender Klassen zeigen.
Man sagt
Basisklasse und Interface sind zuweisungskompatibel zu abgeleiteten und implementierenden Klassen.
Dieses Prinzip gehört zu den mächtigsten Konzepten der objektorientierten Programmierung.
Beispiel:
abstract class Musikinstrument{
public abstract void spielt();
}
class Geige extends Musikinstrument{
private Klang
klang = new Klang("/sound/geige.mp3");
@
Override
public void spielt(){
klang.play();
}
}
class
Bratsche extends Musikinstrument{
class Cello extends Musikinstrument{
...
...
@ Override
@
Override
public void
spielt(){
public void spielt(){
...
...
} }
} }
Wenn wir jetzt ein Streichquartett programmieren, können wir verschiedene
Instrumente in Variablen vom Typ Musikinstrument speichern:
class
StreichQuartett{
Musikinstrument m1, m2, m3, m4;
public
StreichQuartett(Musikinstrument m1, Musikinstrument m2, Musikinstrument
m3, Musikinstrument m4){
this.m1 = m1;
this.m2 = m2;
this.m3 = m3;
this.m4 = m4;
}
public void
zusammenSpielen(){
m1.spiel();
m2.spiel();
m3.spielt();
m4.spielt();
}
}
Diese Klasse muss gar nicht wissen, um welche Instrumente es sich handelt, sie weiß nur, dass ein Musikinstrument eine Methode spielt() hat. Es können zwei Geigen ein Cello und eine Bratsche sein oder eine andere Zusammensetzung: die Klasse StreichQuartett muss nicht umgeschrieben oder neu kompiliert werden. Musikinstrument kann viele Gestalten annehmen - deshalb Polymorphie.
Noch wichtiger: StreichQuartett funktioniert auch mit zukünftigen Klassen, die von Musikinstrument abgeleitet sind. Wenn wir also zusätzlich die Klasse ViolinCello schreiben, änder sich nicht am Streichquartett.
Auch im Zusammenhang mit einem Interface gilt diese Regel: Klassen, die ein Interface verwenden müssen nicht neu kompiliert werden, wenn es neue Klassen gibt, welche das Interface implementieren.
Man kann mit einer Referenz vom Typ einer Basisklasse oder eines Interface nur auf Methoden der Basisklasse bzw. des Interface zugreifen.
Beispiel:
class Orgel extends Musikinstrument{
@ Override
public void spielt(){ ... }
public void registerWaehlen(String register){
.... }
}
...
Musikinstrument orgel = new Orgel();
orgel.spiel(); //
geht
orgel.registerWaehlen("Kornett"); // geht nicht, obwohl das Objekt vom Typ Orgel
ist
Weiterführende Links
Kapitel zu Polymorphie in Java ist auch eine Insel