Direkt zum Hauptinhalt springen
eLearner.app
Modul 3 · Lektion 2 von 26/14 im Kurs~15 min
Lektionen des Moduls (2/2)

Polymorphie und abstrakte Klassen

Polymorphismus und abstrakte Klassen sind fortgeschrittene Konzepte der objektorientierten Programmierung, die es ermöglichen, flexiblen, erweiterbaren und von spezifischen Implementierungen unabhängigen Code zu schreiben.

Polymorphismus

Der Begriff Polymorphismus (Vielgestaltigkeit) bezieht sich auf die Fähigkeit, Objekte verschiedener Klassen so zu behandeln, als gehörten sie zu einem gemeinsamen Typ. In Java kann eine Variable vom Typ einer Superklasse eine Referenz auf ein Objekt einer beliebigen Unterklasse speichern.

Code
class Animal {
    public void makeSound() {
        System.out.println("Verso...");
    }
}

class Dog extends Animal {
    public void makeSound() {
        System.out.println("Woof");
    }
}

class Cat extends Animal {
    public void makeSound() {
        System.out.println("Miao");
    }
}

Dank Polymorphismus können wir Folgendes tun:

Code
Animal myAnimal1 = new Dog(); // Polimorfismo
Animal myAnimal2 = new Cat(); // Polimorfismo

myAnimal1.makeSound(); // Esegue il metodo di Dog (Woof)
myAnimal2.makeSound(); // Esegue il metodo di Cat (Miao)

Die Entscheidung, welche Methode aufgerufen werden soll, wird zur Laufzeit (Late Binding oder dynamischer Dispatch) basierend auf dem tatsächlichen Objekt und nicht auf dem Typ der Referenzvariable getroffen.

Abstrakte Klassen (abstract)

Eine abstrakte Klasse ist eine mit dem Schlüsselwort abstract gekennzeichnete Klasse, die nicht direkt instanziiert werden kann (Sie können kein new MyAbstractClass() machen). Sie dient als "Teilvorlage" für andere Klassen.

Abstrakte Methoden

Eine abstrakte Klasse kann abstrakte Methoden enthalten: Methoden, die ohne Körper (ohne geschweifte Klammern und ohne Code) deklariert werden und mit einem Semikolon enden. Nicht-abstrakte Unterklassen sind verpflichtet, alle geerbten abstrakten Methoden zu implementieren.

Code
abstract class Shape {
    String color;

    // Metodo astratto (senza corpo)
    public abstract double getArea();
}

class Circle extends Shape {
    double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    // Obbligatorio implementare getArea
    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

Dynamic Binding / Late Binding

Woher weiß Java zur Laufzeit, welche Methode ausgeführt werden soll? Dieser Prozess wird als Late Binding (oder Dynamic Binding) bezeichnet. Im Gegensatz zum Überladen (das zur Compilezeit aufgelöst wird) weiß der Compiler nicht, welche spezifische Methode ausgeführt wird. Stattdessen generiert er eine generische Aufrufanweisung. Zur Laufzeit untersucht die Java Virtual Machine (JVM) das reale Objekt im Speicher und ruft die in der Klasse dieses Objekts definierte Methodenimplementierung auf.

Abstrakte Klassen und fehlende Implementierung

Wenn eine Unterklasse von einer abstrakten Klasse erbt, hat sie zwei Optionen:

  1. Alle abstrakten Methoden implementieren: In diesem Fall kann die Klasse eine normale (konkrete) Klasse sein und instanziiert werden.
  2. Sich selbst als abstrakt deklarieren: Wenn die Unterklasse keine Implementierung für alle geerbten abstrakten Methoden bereitstellt, muss sie ihrerseits mit dem Schlüsselwort abstract deklariert werden.
Code
abstract class Animal {
    public abstract void makeSound();
}

// Questa classe DEVE essere astratta perché non implementa makeSound()
abstract class Canine extends Animal {
    // Eredita makeSound() ma non lo implementa
}

Probiere es aus

Übung#java.m3.l2.e1
Versuche: 0Wird geladen…

Deklarieren Sie eine Variable s vom Typ Shape und weisen Sie ihr mithilfe von Polymorphismus ein neues Circle-Objekt zu.

Editor wird geladen…
Hinweis anzeigen

Schreiben Sie `Shape s = new Circle();`, um den Basistyp als Referenztyp zu verwenden.

Lösung nach 3 Versuchen verfügbar

Übung#java.m3.l2.e2
Versuche: 0Wird geladen…

Machen Sie die Klasse Shape abstrakt und fügen Sie die abstrakte Methode double getArea() hinzu. Vervollständigen Sie dann Square so, dass es Shape erweitert und getArea() implementiert, indem es side * side zurückgibt.

Editor wird geladen…
Hinweis anzeigen

Deklarieren Sie `public abstract double getArea();` in Shape. In Square fügen Sie `@Override public double getArea() { return side * side; }` hinzu.

Lösung nach 3 Versuchen verfügbar

Übung#java.m3.l2.e3
Versuche: 0Wird geladen…

Deklarieren Sie in der main-Methode ein Array vom Typ Shape[], das ein Circle-Objekt mit Radius 2.0 und ein Square-Objekt mit der Seitenlänge 3.0 enthält. Verwenden Sie anschließend eine Schleife (for oder for-each), um die Fläche jeder Form durch Aufrufen der Methode getArea() auf der Konsole auszugeben.

Editor wird geladen…
Hinweis anzeigen

Deklarieren Sie das Array mit `Shape[] shapes = { new Circle(2.0), new Square(3.0) };` und durchlaufen Sie es mit einer Schleife `for (Shape s : shapes)` unter Ausgabe von `s.getArea()`.

Lösung nach 3 Versuchen verfügbar