9.2 Polymorphie beim Überschreiben

Java erlaubt es Methoden von Oberklassen in Unterklassen zu verdecken und neu zu implementieren. Hierdurch können Methoden an die Anforderungen einer spezialisierten Klasse angepasst werden. Man spricht hier vom Überschreiben von Methoden wenn die folgende Definition gilt:

Definition
Überschreiben einer Methode
Bei einer überschriebenen Methode müssen die Signatur und der Rückgabewert der überschriebenen Methode identisch mit der Signatur und dem Rückgabewert der Methode einer Oberklasse sein.

Beim Überschreiben von Methoden und Attributen ist das "Liskov Substitution Principle" nicht mehr automatisch garantiert. Hier wir die überschreibende Methode der Unterklasse an die Stelle der überschriebenen Methode der Oberklasse bei allen Instanzen der Unterklasse verwendet. Es wird ein anderer Code ausgeführt. Dieser Code könnte theoretisch auch zu einem anderen Verhalten führen.

Anbei das Beispiel einer Klasse Point, die einen zweidimensionalen Punkt modelliert und der Klasse CircleIsPoint die von Punkt erbt und zusätzlich ein Attribut zur Verwaltung des Radius hat:

Klasse Point

public class Point {
    private double x;
    private double y;

    public Point(double xx, double yy) {
        x = xx;
        y = yy;
    }
    public void setXY(double xx, double yy) {
        x = xx;
        y = yy;
    }
    public double getX() { return x;}
    public double getY() { return y;}

    public void print() {System.out.println(toString());}
    public String toString() {return ("x: " + x + " y: " + y);}
}

Klasse CircleIsPoint

public class CircleIsPoint extends Point{
    private double radius;

    public CircleIsPoint(double xx, double yy, double r) {
        super(xx,yy);
        radius=r;
    }
    public double getRadius() {return radius;}
    public void setRadius(double r) {radius=r;}

    public void print() { //Ueberschriebene Methode
        System.out.println(super.toString() + " radius: " + radius);
    }
}

Ein Hauptprogramm

public class Main {
    public static void main(String[] args) {
        Point[] pf = new Point[3];
        pf[0] = new Point (2.2, 3.3);
        pf[1] = new Point (7.7, 8.8);
        pf[2] = new CircleIsPoint(4.4,5.5,6.6);

        pf[0].print();
        pf[1].print();
        pf[2].print();
    }
}

Bei der Ausführung des Programms ergibt sich die folgende Objekstruktur:

Die Ausgabe ist die folgende:

x: 2.2 y: 3.3
x: 7.7 y: 8.8
x: 4.4 y: 5.5 radius: 6.6

Die überschriebene print() Methode erzeugt eine sinnvolle Ausgabe, die zusätzlich den Radius ausgibt ohne das das komsumierende Hauptprogramm "weiß", das es sich um eine überschriebene Methode handelt.

Da der Begriff einer "sinnvollen" Erweiterung nicht von Werkzeugen abgeprüft werden kann, ergibt sich ein Risiko des Missbrauchs. Ein Beispiel ist die folgende Implementierung der Methode print() in der Klasse CircleIsPoint().

public class CircleIsPoint extends Point{
    ...
    public void print() {
        System.out.println("Methode print() muss noch implementiert werden...");
    }
}

Der Unterschied zwischen der recht menschlichen Implementierung und der Implementierung die auch den Radius ausgibt ist nur gering.

Es gibt im schlimmsten Fall Programme, die diesen Text lesen und weder die zusätzlichen Information über den Radius interpretieren können, noch mit einem anderen Text umgehen können.

Ist eine Klasse und/oder die Methode nicht als final deklariert, muss ein Konsument dieser Klasse mit einem Überschreiben von Methoden rechnen!

Hiermit ergibt sich für den Polymorphismus beim Überschreiben die folgende Abschätzung:

Vorteil Nachteil
Kostensenkung Entwicklung: Existierender Code kann unmodifiziert mit neuen Unterklassen umgehen Kostensteigerung QA und Service: Der Polymorphismus kann durch Missbrauch zu unerwarteten Effekten führen, die erst zur Laufzeit auftreten.

Begriffsbestimmung: Überschriebene und überladene Methoden

Es gibt in Java überschriebene (englisch overriding) und überladene (englisch overloading) Methoden. Beide Begriffe werden leicht verwechselt!

  Überschriebene Methode Überladene Methode
Methodenname identisch identisch
Eingabeparameterliste identisch (Typen, Anzahl, Folge) unterschiedlich!
Rückgabewert identisch nicht relevant
Klassenbeziehung der Methoden Methoden gehören zu unterschiedlichen Klassen die aber in einer Ober- Unterklassebeziehung stehen Methoden gehören zur gleichen Klasse

Zur vollständigen Begriffsverwirrung: Methoden können andere Methoden der gleichen Klasse überladen während sie eine Methode der Oberklasse überschreiben.

Siehe die Methode mult() im folgenden Beispiel:

Überschriebene und überladene Methoden

Anonymous (not verified)

Mon, 12/01/2014 - 01:40

Kann es sein dass hier ein Fehler vorliegt?
"Hier tritt nun die überschreibende Methode an die Stelle der überschriebenen Methode."

Anonymous (not verified)

Wed, 12/17/2014 - 16:23

Sollte die Ausgabe beim Ausführen der Methode main() in der Klasse Main nicht

x: 2.2 y: 3.3
x: 7.7 y: 8.8
x: 4.4 y: 5.5 radius: 6.6

sein?

(Vielleicht haben sie sich bei der zweiten Zeile beim y verschrieben.)