Dynamisches Binden und Überlagern von Methoden in Java

Dynamisches Binden und Überlagern von Methoden in Java

In Java werden Methoden der Vaterklasse an die abgeleiteten Klassen vererbt. Die vererbten Methoden können dann in den abgeleiteten Klassen neu definiert werden. Dieser Vorgang wird in Java als Überlagern von Methoden bezeichnet.

Arten von Methoden in einer abgeleiteten Klasse

In einer abgeleiteten Klasse können drei Arten von Methoden vorhanden sein:

  • In der Tochterklasse definierte neue Methoden
  • Von der Vaterklasse geerbte unveränderte Methoden
  • Von der Vaterklasse geerbte überlagerte Methoden, die in der Tochterklasse neu definiert wurden

Wurde eine Methode überlagert (d.h. in der abgeleiteten Klasse neu definiert), wird beim Aufrufen der Methode auf Objekten dieses Datentyps immer die überlagerte Version verwendet.

Beispielanwendung für die Methodenüberlagerung in Java

In dem folgenden Beispiel wird die Klasse Saeugetier von der Basisklasse Lebewesen abgeleitet. Dadurch erbt die Saeugetier-Klasse die Merkmale der Basisklasse. Wir testen die Anwendung mittels der Klasse MethodenÜberlagern.

public class MethodenÜberlagern {
    public static void main (String[] args) {
        Lebewesen tier1 = new Lebewesen();
        System.out.println("Tier 1 -> Lebewesen tier1 = new Lebewesen();n");
        System.out.println("Datentyp der Referenzvariable = Lebewesen");
        System.out.println("Datentyp der Instanz = Lebewesen");
        System.out.println("Tierart = " + tier1.getArt());

        Lebewesen tier2 = new Saeugetier();
        System.out.println("nTier 2 -> Lebewesen tier2 = new Saeugetier();n");
        System.out.println("Datentyp der Referenzvariable = Lebewesen");
        System.out.println("Datentyp der Instanz = Saeugetier");
        System.out.println("Tierart = " + tier2.getArt());

        Saeugetier tier3 = new Saeugetier();
        tier3.tragzeit = 33;
        System.out.println("nTier 3 -> Saeugetier tier3 = new Saeugetier();n");
        System.out.println("Datentyp der Referenzvariable = Saeugetier");
        System.out.println("Datentyp der Instanz = Saeugetier");
        System.out.println("Tierart = " + tier3.getArt());
        System.out.println("Tragzeit = " + tier3.getTragzeit() + " Wochen");
    }
}

class Lebewesen {
    String getArt() {
        return "Lebewesen";
    }
}

class Saeugetier extends Lebewesen {
    short tragzeit;

    short getTragzeit() {
        return this.tragzeit;
    }

    String getArt() {
        return "Saeugetier";
    }
}

Dynamisches Binden in Java

In Java werden Methoden immer über Objekte aufgerufen. Je nach Objekttyp wird entweder die Version der Basisklasse oder die überlagerte Version der abgeleiteten Klasse aufgerufen.

LESEN  Taxonomische Überprüfung von Metaxia (Gastropoda: Triphoridae) aus Brasilien mit Beschreibung einer neuen Art

Eine überlagerte Methode hat immer Vorrang. Welche Version aufgerufen wird, hängt vom Datentyp des Objekts ab, über das die Methode aufgerufen wird.

In dem Beispielcode wird die Methode getArt() in der Basisklasse Lebewesen definiert. In der abgeleiteten Klasse Saeugetier wird diese Methode überlagert und neu definiert. Dadurch wird die Methode getArt() zweimal definiert, einmal in der Basisklasse und einmal in der abgeleiteten Klasse.

Beim Aufruf der Methode getArt() wird immer die überlagerte Version aufgerufen, wenn das Objekt vom Typ Saeugetier ist. Ist das Objekt vom Typ Lebewesen, wird die Version aus der Basisklasse aufgerufen.

Dieses Konzept wird als Dynamisches Binden bezeichnet.

Performance-Verschlechterung durch Überlagern von Methoden

Beim Dynamischen Binden wird erst zur Laufzeit entschieden, welche Version einer überlagerten Methode aufgerufen werden soll. Dadurch muss der Compiler zusätzlichen Code generieren, was zu einer Verschlechterung der Performance von Java-Anwendungen führen kann.

Um die Performance zu verbessern, sollten so oft wie möglich statische Methodenaufrufe anstelle von dynamischen Aufrufen verwendet werden. Methoden können als private, final oder static deklariert werden, um sicherzustellen, dass sie nicht überlagert werden können.

Verdeckte Methoden mit Hilfe des Schlüsselworts super aufrufen

Durch die Methodenüberlagerung wird immer die überlagerte Version einer Methode aufgerufen. Möchte man bereits vorhandene Funktionalität wiederverwenden, ist es aber notwendig, die verdeckten Methoden der Vaterklasse (Superklasse) aufrufen zu können.

In Java kann dies mit Hilfe des Schlüsselworts super erreicht werden. Mit super.Methodenname() wird die Methode der Vaterklasse aufgerufen, also die Superklassen-Methode.

Es ist wichtig, die Unterschiede zwischen den Schlüsselwörtern super und this zu verstehen. this wird innerhalb von Instanzen verwendet und bezieht sich auf das aktuelle Objekt, über das die Methode oder der Konstruktor aufgerufen wurde. super verweist auf die Superklasse der aktuellen Instanz.

LESEN  Was macht eine Hülsenmarkise aus?

Im folgenden Beispiel wird der Unterschied zwischen den Schlüsselwörtern this und super verdeutlicht:

public class SuperAndThisTest {
    public static void main (String[] args) {
        Subclass sub = new Subclass(19, 84);
        sub.printMethod();
    }
}

class Superclass {
    int x, y;

    public Superclass(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public void printMethod() {
        System.out.println("nAusgegeben in der Superclass.");
    }
}

class Subclass extends Superclass {
    int x;
    int y = super.y - 3;

    public Subclass(int x, int y) {
        super(x, y); // ruft den Konstruktor der Superclass auf
    }

    public void printMethod() {
        int y = 80;
        super.printMethod(); // ruft printMethod der Superclass auf
        System.out.println("nAusgegeben in der Subclass.");
        System.out.println("Variable x = " + x);
        System.out.println("Variable this.x = " + this.x);
        System.out.println("Variable super.x = " + super.x);
        this.x = 20;
        System.out.println("nVariable this.x = " + x);
        System.out.println("Variable super.x = " + super.x);
        System.out.println("nVariable y = " + y);
        System.out.println("Variable this.y = " + this.y);
        System.out.println("Variable super.y = " + super.y);
    }
}

Neben Methoden können auch Variablen überlagert werden. Im Beispielcode gibt es mehrere Überlagerungen der Variablen x und y. Die Variable y wird dreifach überlagert.

Beim Zugriff auf die Variable y werden die Unterschiede zwischen super.y und this.y deutlich. super.y greift auf die Variable y der Superklasse zu, während this.y auf die Variable y der aktuellen Instanz zugreift.