Innere, verschachtelte & anonyme Klassen
Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy. Lektion 49 von 87.
Java ermöglicht es Ihnen, Klassen innerhalb anderer Klassen zu definieren. Diese inneren Klassen helfen dabei, Code zu organisieren, indem sie verwandte Funktionalitäten gruppieren, und können direkt auf die Member der äußeren Klasse zugreifen.
Eine geschachtelte innere Klasse ist als Mitglied einer anderen Klasse definiert. Sie hat Zugriff auf alle Felder und Methoden der äußeren Klasse, einschließlich privater:
class Outer {
private String message = "Hello";
class Inner {
void display() {
System.out.println(message); // Kann auf privates Feld zugreifen
}
}
}
// Verwendung
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.display(); // Gibt aus: HelloEine lokale innere Klasse wird innerhalb einer Methode definiert. Sie kann nur innerhalb dieser Methode verwendet werden und auf lokale Variablen zugreifen, die effektiv final sind:
void process() {
String prefix = "Result: ";
class LocalHelper {
void print(int value) {
System.out.println(prefix + value);
}
}
new LocalHelper().print(42);
}Eine anonyme innere Klasse ist eine Klasse ohne Namen, die in einem einzigen Ausdruck erstellt und instanziiert wird. Sie wird häufig verwendet, um Schnittstellen zu implementieren oder Klassen spontan zu erweitern:
Comparator<String> comp = new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.length() - b.length();
}
};Innere Klassen sind besonders nützlich, wenn eine Klasse nur für eine andere Klasse relevant ist, wodurch Ihr Code organisiert und gekapselt bleibt.
Aufgabe
EinfachErstellen wir ein Warenkorbsystem, das alle drei Arten innerer Klassen demonstriert. Du erstellst einen ShoppingCart, der eine verschachtelte innere Klasse zur Darstellung von Artikeln, eine lokale innere Klasse zur Berechnung von Rabatten und eine anonyme innere Klasse zur Formatierung des endgültigen Belegs verwendet.
Du organisierst deinen Code über zwei Dateien:
ShoppingCart.java: Erstelle die äußere Klasse, die ein Einkaufserlebnis verwaltet. Dein ShoppingCart sollte ein privates FeldcustomerName(String) besitzen.Definiere innerhalb von ShoppingCart eine verschachtelte innere Klasse namens
Itemmit zwei privaten Feldern:name(String) undprice(double). Gib Item einen Konstruktor, der beide Felder initialisiert, sowie eine MethodegetDetails(), die Folgendes zurückgibt:[name]: $[price]Dein ShoppingCart benötigt einen Konstruktor, der den Kundennamen entgegennimmt, sowie eine Methode namens
checkout(), die ein Item und einen Rabattprozentsatz (double) akzeptiert. Innerhalb voncheckout():- Erstelle eine lokale innere Klasse namens
DiscountCalculatormit einer MethodeapplyDiscount(double originalPrice), die den Preis nach Anwendung des Rabattprozentsatzes zurückgibt. - Verwende die lokale Klasse, um den Endpreis zu berechnen.
- Erstelle eine anonyme innere Klasse, die das
Formatter-Interface implementiert (dieses definierst du selbst), um den Beleg zu formatieren. Die anonyme Klasse sollte eineformat()-Methode überschreiben, die einen mehrzeiligen Belegtext zurückgibt.
Die Methode
checkout()sollte den formatierten Beleg in genau diesem Format zurückgeben:--- Receipt --- Customer: [customerName] Item: [item details from getDetails()] Discount: [discount]% Final Price: $[calculated price]- Erstelle eine lokale innere Klasse namens
Formatter.java: Definiere ein einfaches Interface mit einer einzigen Methode:String format(). Dieses Interface wird von deiner anonymen inneren Klasse innerhalb der checkout-Methode implementiert.Main.java: Erwecke deinen Warenkorb zum Leben! Du erhältst drei Eingaben: Kundenname (String), Artikelname (String) und Artikelpreis (double). Der Rabattprozentsatz ist fest auf10.0gesetzt.Erstelle einen ShoppingCart mit dem Kundennamen. Erstelle anschließend ein Item mithilfe der Syntax für die Referenz auf die äußere Klasse:
cart.new Item(name, price). Rufecheckout()mit dem Item und dem Rabatt auf und gib den zurückgegebenen Beleg aus.
Du erhältst drei Eingaben in dieser Reihenfolge: Kundenname, Artikelname und Artikelpreis.
Wenn die Eingaben beispielsweise Alice, Laptop und 1000.0 lauten, beträgt der Endpreis nach einem Rabatt von 10 % 900.0.
Beachte, wie jeder Typ innerer Klasse einem anderen Zweck dient: Die verschachtelte Klasse gruppiert zugehörige Daten mit der äußeren Klasse, die lokale Klasse kapselt Logik, die nur innerhalb einer Methode benötigt wird, und die anonyme Klasse bietet eine schnelle, einmalige Implementierung eines Interfaces!
Probier es selbst
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Eingaben lesen
String customerName = scanner.nextLine();
String itemName = scanner.nextLine();
double itemPrice = scanner.nextDouble();
double discount = 10.0;
// TODO: Erstelle einen ShoppingCart mit dem Kundennamen
// TODO: Erstelle ein Item mit: cart.new Item(itemName, itemPrice)
// TODO: Rufe checkout() mit dem Item und dem Rabatt auf und gib das Ergebnis aus
}
}
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