Menu
Coddy logo textTech

Methodenüberschreibung (Laufzeit)

Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy — Lektion 29 von 87.

Während Method Overloading zur Kompilierzeit aufgelöst wird, demonstriert Method Overriding den Laufzeit-Polymorphismus. Hierbei entscheidet Java erst während der Programmausführung, welche Methode ausgeführt werden soll, basierend auf dem tatsächlichen Typ des Objekts und nicht auf dem deklarierten Typ der Variablen.

Sie haben im Kapitel über Vererbung etwas über das Überschreiben von Methoden gelernt. Was es polymorph macht, ist die Art und Weise, wie Java damit umgeht, wenn eine Referenz der Elternklasse auf ein Objekt der Kindklasse verweist:

public class Animal {
    public void speak() {
        System.out.println("Some sound");
    }
}

public class Dog extends Animal {
    @Override
    public void speak() {
        System.out.println("Bark!");
    }
}

public class Cat extends Animal {
    @Override
    public void speak() {
        System.out.println("Meow!");
    }
}

Beobachten Sie nun, was passiert, wenn wir Referenzen vom Typ der Elternklasse verwenden:

Animal myPet = new Dog();
myPet.speak();  // Ausgabe: Bark!

myPet = new Cat();
myPet.speak();  // Ausgabe: Meow!

Obwohl myPet als Animal deklariert ist, ruft Java die überschriebene Methode basierend auf dem tatsächlichen Objekttyp zur Laufzeit auf. Dies wird als dynamischer Methodenaufruf bezeichnet. Die JVM schaut sich an, was das Objekt wirklich ist, nicht was die Variable besagt.

Dies ermöglicht leistungsstarke Muster, wie die einheitliche Verarbeitung verschiedener Objekte:

Animal[] pets = {new Dog(), new Cat(), new Dog()};
for (Animal pet : pets) {
    pet.speak();  // Jedes ruft seine eigene Version auf
}

Laufzeit-Polymorphismus ermöglicht es Ihnen, flexiblen Code zu schreiben, der mit Elterntypen arbeitet, während er automatisch das korrekte Verhalten der Kindtypen verwendet.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Benachrichtigungssystem bauen, das Laufzeit-Polymorphismus in Aktion demonstriert. Sie werden eine Hierarchie von Benachrichtigungstypen erstellen, bei denen derselbe Methodenaufruf je nach tatsächlichem Objekttyp zur Laufzeit unterschiedliche Ausgaben erzeugt.

Sie werden Ihren Code über vier Dateien organisieren:

  • Notification.java: Erstellen Sie die Basisklasse, die alle Benachrichtigungen gemeinsam haben. Jede Benachrichtigung hat ein recipient-Feld (String). Fügen Sie einen Konstruktor zur Initialisierung, eine Getter-Methode und eine send()-Methode hinzu, die Folgendes ausgibt: Sending notification to [recipient]
  • EmailNotification.java: Erstellen Sie eine Klasse, die Notification erweitert. E-Mail-Benachrichtigungen fügen ein subject-Feld hinzu. Verwenden Sie super für die Initialisierung der Elternklasse. Überschreiben Sie die send()-Methode, um Folgendes auszugeben: Emailing [recipient]: [subject]
  • SMSNotification.java: Erstellen Sie eine weitere Klasse, die Notification erweitert. SMS-Benachrichtigungen fügen ein phoneNumber-Feld hinzu. Überschreiben Sie send(), um Folgendes auszugeben: Texting [phoneNumber] for [recipient]
  • Main.java: Hier glänzt der Laufzeit-Polymorphismus! Sie erhalten drei Eingaben: einen Empfängernamen, einen E-Mail-Betreff und eine Telefonnummer. Erstellen Sie ein Array von Notification-Referenzen, das drei Objekte in dieser Reihenfolge enthält: eine Basis-Notification, eine EmailNotification und eine SMSNotification (alle mit demselben Empfänger). Durchlaufen Sie dann das Array in einer Schleife und rufen Sie send() für jedes Element auf. Beobachten Sie, wie Java automatisch die richtige überschriebene Version aufruft, basierend darauf, was jedes Objekt tatsächlich ist!

Sie erhalten drei Eingaben: den Empfängernamen (String), den E-Mail-Betreff (String) und die Telefonnummer (String).

Ihre Ausgabe sollte drei Zeilen zeigen - jeder send()-Aufruf erzeugt eine andere Ausgabe, obwohl Sie dieselbe Methode auf Notification-Referenzen aufrufen. Das ist dynamischer Methodenaufruf (Dynamic Method Dispatch) in Aktion!

Spickzettel

Methoden-Überschreiben demonstriert Laufzeit-Polymorphismus, bei dem Java entscheidet, welche Methode ausgeführt werden soll, wenn das Programm läuft, basierend auf dem tatsächlichen Typ des Objekts und nicht auf dem deklarierten Typ der Variablen.

Wenn eine Referenz der Elternklasse auf ein Kindobjekt zeigt, ruft Java die überschriebene Methode basierend auf dem tatsächlichen Objekttyp zur Laufzeit auf:

public class Animal {
    public void speak() {
        System.out.println("Some sound");
    }
}

public class Dog extends Animal {
    @Override
    public void speak() {
        System.out.println("Bark!");
    }
}

Animal myPet = new Dog();
myPet.speak();  // Output: Bark!

myPet = new Cat();
myPet.speak();  // Output: Meow!

Dies wird als dynamische Methodenbindung (dynamic method dispatch) bezeichnet. Die JVM schaut darauf, was das Objekt wirklich ist, nicht darauf, was die Variable besagt.

Laufzeit-Polymorphismus ermöglicht die einheitliche Verarbeitung verschiedener Objekte:

Animal[] pets = {new Dog(), new Cat(), new Dog()};
for (Animal pet : pets) {
    pet.speak();  // Jedes ruft seine eigene Version auf
}

Probier es selbst

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Eingaben lesen
        String recipient = scanner.nextLine();
        String subject = scanner.nextLine();
        String phoneNumber = scanner.nextLine();
        
        // TODO: Erstelle ein Array von Notification-Referenzen mit 3 Elementen
        // Das Array sollte (in dieser Reihenfolge) Folgendes enthalten:
        // 1. Ein Basis-Notification-Objekt
        // 2. Ein EmailNotification-Objekt
        // 3. Ein SMSNotification-Objekt
        // Alle verwenden denselben recipient
        
        // TODO: Iteriere durch das Array und rufe send() für jedes Element auf
        // Dies demonstriert Laufzeit-Polymorphismus!
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung