Menu
Coddy logo textTech

Komposition vs. Vererbung

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

Vererbung erzeugt eine „ist-ein“-Beziehung: ein Dog ist ein Animal. Aber was ist, wenn eine Klasse Funktionalität von etwas benötigt, das sie nicht ist? Hier kommt die Komposition ins Spiel, die stattdessen eine „hat-ein“-Beziehung herstellt.

Bei der Komposition enthält eine Klasse Instanzen anderer Klassen als Felder, anstatt sie zu erweitern:

// Vererbungsansatz: Auto IST ein Motor (macht keinen Sinn)
class Car extends Engine { }

// Kompositionsansatz: Auto HAT einen Motor (macht Sinn)
class Car {
    private Engine engine;
    
    public Car(Engine engine) {
        this.engine = engine;
    }
    
    public void start() {
        engine.ignite();
    }
}

Komposition bietet mehrere Vorteile. Sie können das zusammengesetzte Objekt zur Laufzeit ändern, wie zum Beispiel das Austauschen von Motoren.

Sie können auch Verhaltensweisen aus mehreren Klassen kombinieren, was durch Vererbung in Java nicht möglich ist. Die zusammengesetzte Klasse legt nur die Methoden offen, die sie selbst bestimmt, was eine bessere Kapselung bietet.

Ein praktischer Leitfaden: Verwenden Sie Vererbung, wenn eine echte „is-a“-Beziehung besteht und die Unterklasse tatsächlich eine spezialisierte Version der Elternklasse darstellt.

Verwenden Sie Komposition, wenn Sie die Funktionalität einer anderen Klasse nutzen müssen, ohne dieser Typ zu sein. Viele erfahrene Entwickler folgen dem Prinzip: „Komposition gegenüber Vererbung bevorzugen“, da dies zu flexiblerem, wartbarerem Code führt.

challenge icon

Aufgabe

Einfach

Lassen Sie uns ein Computersystem mittels Komposition aufbauen, um die „hat-ein“-Beziehung (has-a) zu demonstrieren. Anstatt dass ein Computer von seinen Komponenten erbt (was keinen Sinn ergeben würde), wird Ihr Computer die Teile, die er zum Funktionieren benötigt, enthalten.

Sie werden Ihren Code über drei Dateien organisieren:

  • Processor.java: Erstellen Sie eine Klasse, die eine CPU repräsentiert. Ein Processor hat zwei private Felder: brand (String) und speedGHz (double). Fügen Sie einen Konstruktor zur Initialisierung beider Felder und Getter-Methoden für jedes Feld hinzu. Fügen Sie eine Methode process() hinzu, die einen String zurückgibt: [brand] processing at [speedGHz] GHz
  • Memory.java: Erstellen Sie eine Klasse, die den Arbeitsspeicher (RAM) repräsentiert. Ein Memory hat zwei private Felder: type (String, wie "DDR4" oder "DDR5") und sizeGB (int). Fügen Sie einen Konstruktor, Getter und eine Methode load() hinzu, die Folgendes zurückgibt: Loading [sizeGB]GB [type] memory
  • Computer.java: Hier glänzt die Komposition! Ihre Computer-Klasse sollte einen Processor und einen Memory als private Felder haben – sie erweitert diese nicht, sie enthält sie. Fügen Sie einen Konstruktor hinzu, der beide Komponenten akzeptiert. Fügen Sie eine Methode boot() hinzu, die einen mehrzeiligen String zurückgibt, der den Startvorgang des Computers unter Verwendung seiner Komponenten zeigt:
    Booting computer...
    [processor.process() result]
    [memory.load() result]
    System ready!
    Fügen Sie außerdem eine Methode getSpecs() hinzu, die Folgendes zurückgibt: Specs: [processor brand] CPU, [memory sizeGB]GB [memory type]
  • Main.java: Erwecken Sie Ihr zusammengesetztes System zum Leben! Sie erhalten vier Eingaben: Prozessor-Marke (String), Prozessor-Geschwindigkeit (double), Speichertyp (String) und Speichergröße (int).

    Erstellen Sie einen Processor und einen Memory mit diesen Werten und setzen Sie diese dann zu einem Computer zusammen. Geben Sie das Ergebnis des Aufrufs von boot() aus und geben Sie anschließend das Ergebnis von getSpecs() aus.

Sie erhalten vier Eingaben in der folgenden Reihenfolge: Prozessor-Marke, Prozessor-Geschwindigkeit (GHz), Speichertyp und Speichergröße (GB).

Beachten Sie, wie der Computer Aufgaben an seine Komponenten delegiert, anstatt zu versuchen, diese selbst zu sein – das ist die Stärke der Komposition! Der Computer kann jeden Processor oder Memory verwenden, den Sie ihm geben, was das Design flexibel und realistisch macht.

Spickzettel

Komposition erzeugt eine „hat-ein“-Beziehung, bei der eine Klasse Instanzen anderer Klassen als Felder enthält, anstatt sie zu erweitern.

Vererbung vs. Komposition:

// Vererbung: Car IST ein Engine (macht keinen Sinn)
class Car extends Engine { }

// Komposition: Car HAT einen Engine (macht Sinn)
class Car {
    private Engine engine;
    
    public Car(Engine engine) {
        this.engine = engine;
    }
    
    public void start() {
        engine.ignite();
    }
}

Vorteile der Komposition:

  • Objekte können zur Laufzeit geändert werden
  • Kann Verhaltensweisen von mehreren Klassen kombinieren
  • Bessere Kapselung – nur ausgewählte Methoden werden offengelegt
  • Flexiblerer und wartungsfreundlicherer Code

Wann man was verwendet:

  • Vererbung: Verwenden Sie diese, wenn eine echte „ist-ein“-Beziehung besteht und die Unterklasse eine spezialisierte Version der Elternklasse ist
  • Komposition: Verwenden Sie diese, wenn Sie die Funktionalität einer anderen Klasse benötigen, ohne von diesem Typ zu sein

Best Practice: „Bevorzugen Sie Komposition gegenüber Vererbung“

Probier es selbst

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Eingaben lesen
        String processorBrand = scanner.nextLine();
        double processorSpeed = Double.parseDouble(scanner.nextLine());
        String memoryType = scanner.nextLine();
        int memorySize = Integer.parseInt(scanner.nextLine());
        
        // TODO: Erstelle einen Processor mit der Marke und Geschwindigkeit
        
        // TODO: Erstelle einen Memory mit dem Typ und der Größe
        
        // TODO: Erstelle einen Computer durch Zusammensetzen von Processor und Memory
        
        // TODO: Gib das Ergebnis von boot() aus
        
        // TODO: Gib das Ergebnis von getSpecs() aus
    }
}
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