Warum keine Mehrfachvererbung von Klassen
Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy. Lektion 26 von 87.
Java verhindert absichtlich, dass eine Klasse mehr als eine Klasse erweitert. Diese Einschränkung existiert aufgrund eines Problems, das als das Diamond-Problem bekannt ist.
Stellen Sie sich vor, Java würde Mehrfachvererbung erlauben. Betrachten Sie dieses hypothetische Szenario:
// Dieser Code ist in Java NICHT gültig
public class A {
public void greet() {
System.out.println("Hello from A");
}
}
public class B extends A {
@Override
public void greet() {
System.out.println("Hello from B");
}
}
public class C extends A {
@Override
public void greet() {
System.out.println("Hello from C");
}
}
// In Java NICHT erlaubt!
public class D extends B, C { }Wenn Sie greet() für ein D-Objekt aufrufen würden, welche Version sollte ausgeführt werden? Die von B oder C? Diese Mehrdeutigkeit ist das Diamond-Problem, benannt nach der Rautenform, die durch das Vererbungsdiagramm entsteht.
Javas Lösung ist einfach: Es ist nur die Einfachvererbung von Klassen zulässig. Java bietet jedoch eine Alternative. Eine Klasse kann mehrere Interfaces implementieren, worüber Sie in einem der nächsten Kapitel mehr erfahren werden.
Interfaces lösen das Diamond-Problem auf andere Weise und bieten Ihnen Flexibilität ohne die Mehrdeutigkeit.
// Dies IST in Java gültig
public class Dog extends Animal implements Runnable, Comparable<Dog> {
// Kann mehrere Interfaces implementieren
}Diese Designentscheidung hält Javas Vererbungsmodell sauber und vorhersehbar, während sie gleichzeitig eine leistungsstarke Wiederverwendung von Code durch Interfaces ermöglicht.
Aufgabe
EinfachLass uns ein Musik-Player-System erstellen, das die einfache Vererbung von Java demonstriert und zeigt, wie du innerhalb dieser Einschränkung dennoch flexible Designs erreichen kannst.
Stell dir vor, du möchtest einen intelligenten Lautsprecher erstellen, der Funktionen eines Musik-Players und eines Sprachassistenten kombiniert. Da Java das Erweitern mehrerer Klassen nicht erlaubt, musst du deine Hierarchie sorgfältig unter Verwendung einfacher Vererbung entwerfen.
Du wirst vier Dateien erstellen, um deinen Code zu organisieren:
AudioDevice.java: Erstelle die Basisklasse, die alle Audiowiedergabegeräte gemeinsam haben. Sie sollte Folgendes enthalten:- Ein privates Feld für
deviceName(String) - Einen Konstruktor, der den Gerätenamen akzeptiert
- Eine Methode
getDeviceName(), die den Namen zurückgibt - Eine Methode
playSound(), die Folgendes ausgibt:[deviceName]: Playing audio
- Ein privates Feld für
MusicPlayer.java: Erstelle eine Klasse, die AudioDevice erweitert und musikspezifische Funktionen hinzufügt:- Ein privates Feld für
currentSong(String) - Einen Konstruktor, der den Gerätenamen übernimmt und
super(deviceName)verwendet - Eine Methode
setSong(String song), die das aktuelle Lied festlegt - Überschreibe
playSound(), sodass Folgendes ausgegeben wird:[deviceName]: Now playing - [currentSong]
- Ein privates Feld für
SmartSpeaker.java: Erstelle eine Klasse, die MusicPlayer erweitert (nicht sowohl MusicPlayer als auch eine VoiceAssistant-Klasse – das wäre Mehrfachvererbung!). Der intelligente Lautsprecher baut auf dem Musik-Player auf, indem er Sprachfunktionen hinzufügt:- Ein privates Feld für
assistantName(String) - Einen Konstruktor, der den Gerätenamen und den Assistentennamen übernimmt und
super(deviceName)verwendet - Eine Methode
voiceCommand(String command), die Folgendes ausgibt:[assistantName]: Processing "[command]" - Eine Methode
getFullInfo(), die Folgendes ausgibt:[deviceName] with [assistantName] assistant
- Ein privates Feld für
Main.java: Demonstriere deine mehrstufige Vererbungskette. Du erhältst drei Eingaben: einen Gerätenamen (String), einen Assistentennamen (String) und einen Liednamen (String). Erstelle einen SmartSpeaker, lege ein Lied fest und rufe anschließend diese Methoden in der angegebenen Reihenfolge auf:getFullInfo()playSound()voiceCommand("skip to next")
Du erhältst drei Eingaben: den Gerätenamen, den Assistentennamen und den Liednamen.
Beachte, wie SmartSpeaker Musikwiedergabefunktionen erhält, indem die Klasse MusicPlayer in einer Kette erweitert (AudioDevice -> MusicPlayer -> SmartSpeaker), anstatt zu versuchen, mehrere voneinander unabhängige Klassen zu erweitern. Das ist Javas Ansatz, Vererbung sauber und eindeutig zu halten!
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 deviceName = scanner.nextLine();
String assistantName = scanner.nextLine();
String songName = scanner.nextLine();
// TODO: Erstelle einen SmartSpeaker mit deviceName und assistantName
// TODO: Setze den Song mit setSong()
// TODO: Rufe getFullInfo() auf
// TODO: Rufe playSound() auf
// TODO: Rufe voiceCommand("skip to next") auf
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort thisMethodenFelder (Attribute)KonstruktormethodeÜberladen von KonstruktorenRückblick – Einfacher Taschenrechner4Vererbung
Grundlegende Vererbung (extends)Das Schlüsselwort superÜberschreiben von Methoden (@Override)KonstruktorverkettungDie Object-KlasseEinfach- und mehrstufige VererbungWarum keine Mehrfachvererbung von KlassenRückblick – Mitarbeiterhierarchie7Spezielle Methoden & Object-Klasse
toString()-Methodeequals() und hashCode()clone()-MethodecompareTo() und ComparableComparator-SchnittstelleRückblick – Benutzerdefinierte Sortierung2Zugriffsmodifikatoren & Kapselung
Übersicht der ZugriffsebenenGetter- und Setter-MethodenInformationsverbergungDas Schlüsselwort finalRückblick – Bankkontoverwaltung5Polymorphismus
Grundlagen der MethodenüberladungMethodenüberschreibung (Laufzeit)Upcasting und DowncastingDer instanceof-OperatorAbstrakte Klassen und MethodenRückblick – Formrechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungAggregation vs. KompositionInnere, verschachtelte & anonyme KlassenEnums und Enum-MethodenRecords (Java 16+)Versiegelte Klassen (Java 17+)11Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFactory-MusterBuilder-MusterObserver-MusterStrategie-Muster14Abschließende Herausforderungen
E-Learning-PlattformBankingsystemEntwicklung einer SpielfigurFahrzeugvermietungsdienst3Klassen-Props & statische Member
Instanz- vs. statische VariablenStatische MethodenStatische BlöckeKonstanten (static final)Wiederholung – Counter & Utility6Schnittstellen & abstrakte Klassen
Einführung in InterfacesInterfaces implementierenMehrere Interfaces implementierenDefault & Static in InterfacesAbstrakte Klassen vs. InterfacesFunktionale InterfacesRückblick – ZahlungssystemÜbe selbstständig: Online-Java-Compiler