Upcasting und Downcasting
Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy. Lektion 30 von 87.
In der vorherigen Lektion hast du gesehen, wie eine Variable des übergeordneten Typs ein untergeordnetes Objekt enthalten kann: Animal myPet = new Dog(). Diese Zuweisung wird Upcasting genannt und geschieht automatisch, weil ein Dog immer ein Animal ist.
Upcasting bewegt sich in der Vererbungshierarchie nach oben. Es erfolgt implizit und ist immer sicher:
Dog dog = new Dog();
Animal animal = dog; // Upcasting - automatischBeim Upcasting kannst du nur auf Methoden zugreifen, die in der übergeordneten Klasse definiert sind. Die spezifischen Methoden der Kindklasse werden verborgen, obwohl das Objekt darunter weiterhin ein Dog ist.
Downcasting geht in die entgegengesetzte Richtung und wandelt eine Elternreferenz zurück in einen untergeordneten Typ um. Dies erfordert eine explizite Typumwandlung, da es nicht immer sicher ist:
Animal animal = new Dog(); // Upcasting
Dog dog = (Dog) animal; // Downcasting – expliziter Cast erforderlich
dog.bark(); // Jetzt können wir auf Dog-Methoden zugreifenDowncasting ist riskant. Wenn das Objekt nicht tatsächlich der Typ ist, in den du es umwandelst, löst Java zur Laufzeit eine ClassCastException aus:
Animal animal = new Cat();
Dog dog = (Dog) animal; // Kompiliert, stürzt aber zur Laufzeit ab!Der Compiler kann diesen Fehler nicht erkennen, weil er nur die deklarierten Typen sieht. Der tatsächliche Objekttyp ist erst bekannt, wenn das Programm ausgeführt wird. In der nächsten Lektion lernst du, wie du den Typ eines Objekts sicher überprüfst, bevor du ein Downcasting durchführst.
Aufgabe
EinfachErstelle ein Mediaplayer-System, das sowohl Upcasting als auch Downcasting in Aktion demonstriert. Du wirst eine Hierarchie von Medientypen erstellen und üben, zwischen Referenzen auf Eltern- und Kindklassen umzuwandeln.
Du wirst deinen Code auf vier Dateien verteilen:
Media.java: Erstelle die Basisklasse, die von allen Medientypen gemeinsam verwendet wird. Jedes Medienelement hat ein Feldtitle(String). Füge einen Konstruktor hinzu, um es zu initialisieren, eine Getter-MethodegetTitle()und eine Methodeplay(), die Folgendes ausgibt:Playing: [title]Song.java: Erstelle eine Klasse, die Media erweitert. Songs haben ein zusätzliches Feldartist(String). Verwendesuperfür die Initialisierung der Elternklasse. Überschreibeplay(), sodass Folgendes ausgegeben wird:Playing song: [title] by [artist]. Füge eine MethodeshowArtist()hinzu, die Folgendes ausgibt:Artist: [artist]Podcast.java: Erstelle eine weitere Klasse, die Media erweitert. Podcasts haben ein Feldepisode(int). Überschreibeplay(), sodass Folgendes ausgegeben wird:Playing podcast: [title] - Episode [episode]. Füge eine MethodeshowEpisode()hinzu, die Folgendes ausgibt:Episode: [episode]Main.java: Demonstriere Upcasting und Downcasting mit deinen Medientypen. Du erhältst vier Eingaben: einen Songtitel, einen Künstlernamen, einen Podcasttitel und eine Episodennummer.Erstelle zuerst einen Song und caste ihn zu einer Media-Referenz. Rufe
play()für diese Referenz auf, um Laufzeitpolymorphie in Aktion zu sehen.Downcaste anschließend diese Media-Referenz zurück zu einem Song und rufe
showArtist()auf, um auf die kinderspezifische Methode zuzugreifen.Erstelle dann einen Podcast und caste ihn zu einer Media-Referenz. Rufe
play()für diese Referenz auf.Downcaste schließlich diese Media-Referenz zurück zu einem Podcast und rufe
showEpisode()auf.
Du erhältst vier Eingaben: den Songtitel (String), den Künstlernamen (String), den Podcasttitel (String) und die Episodennummer (int).
Deine Ausgabe sollte vier Zeilen enthalten – zwei für den Song (seine Wiedergabeausgabe und die Künstlerinformationen) und zwei für den Podcast (seine Wiedergabeausgabe und die Episodeninformationen). Beachte, wie du durch Upcasting verschiedene Medientypen einheitlich behandeln kannst, während du durch Downcasting auf ihre individuellen Funktionen zugreifen kannst!
Probier es selbst
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Eingaben lesen
String songTitle = scanner.nextLine();
String artistName = scanner.nextLine();
String podcastTitle = scanner.nextLine();
int episodeNumber = scanner.nextInt();
// TODO: Erstelle einen Song und caste ihn zu einer Media-Referenz hoch
// TODO: Rufe play() auf der Media-Referenz auf (demonstriert Polymorphismus)
// TODO: Caste die Media-Referenz zurück zu Song herunter
// TODO: Rufe showArtist() auf der Song-Referenz auf
// TODO: Erstelle einen Podcast und caste ihn zu einer Media-Referenz hoch
// TODO: Rufe play() auf der Media-Referenz auf
// TODO: Caste die Media-Referenz zurück zu Podcast herunter
// TODO: Rufe showEpisode() auf der Podcast-Referenz 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