Abstrakte Klassen und Methoden
Teil des Abschnitts Objektorientierte Programmierung der Java-Journey von Coddy — Lektion 32 von 87.
Manchmal möchten Sie eine Klasse definieren, die als Bauplan dient, aber niemals direkt instanziiert werden sollte. Zum Beispiel ist eine generische Shape-Klasse als Elternklasse sinnvoll, aber wie würde eine „Form“ ohne spezifische Gestalt aussehen? Hier kommen abstrakte Klassen ins Spiel.
Eine abstrakte Klasse wird mit dem Schlüsselwort abstract deklariert und kann nicht instanziiert werden. Sie kann sowohl reguläre Methoden mit Implementierungen als auch abstrakte Methoden ohne Rumpf enthalten:
public abstract class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
// Abstrakte Methode - keine Implementierung
public abstract double getArea();
// Reguläre Methode - hat eine Implementierung
public String getColor() {
return color;
}
}Abstrakte Methoden deklarieren, was eine Unterklasse tun muss, aber nicht wie. Jede nicht-abstrakte Klasse, die eine abstrakte Klasse erweitert, muss Implementierungen für alle abstrakten Methoden bereitstellen:
public class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}Sie können abstrakte Klassen weiterhin als Referenztypen verwenden, was Polymorphismus ermöglicht:
Shape shape = new Circle("red", 5.0);
System.out.println(shape.getArea()); // Ruft die Implementierung von Circle aufAbstrakte Klassen sind ideal, wenn Unterklassen gemeinsamen Code teilen, aber jeweils bestimmte Verhaltensweisen unterschiedlich implementieren müssen. Sie erzwingen einen Vertrag und ermöglichen gleichzeitig die Wiederverwendung von Code.
Aufgabe
EinfachLassen Sie uns ein Gerätesystem bauen, das die Leistungsfähigkeit abstrakter Klassen demonstriert. Sie erstellen eine Basisklasse Appliance, die definiert, was jedes Gerät tun muss, während die spezifischen Gerätetypen genau entscheiden, wie sie es tun.
Sie werden Ihren Code über vier Dateien organisieren:
Appliance.java: Erstellen Sie eine abstrakte Klasse, die als Bauplan für alle Geräte dient. Jedes Gerät hat einbrand-Feld (String) und einwattage-Feld (int). Fügen Sie einen Konstruktor hinzu, der beide Felder initialisiert, Getter-Methoden für jedes Feld und eine reguläre MethodegetInfo(), die Folgendes zurückgibt:[brand] - [wattage]W. Definieren Sie eine abstrakte Methodeoperate(), die Unterklassen implementieren müssen – diese repräsentiert, wie jedes Gerät seine Hauptfunktion ausführt.WashingMachine.java: Erstellen Sie eine konkrete Klasse, die Appliance erweitert. Waschmaschinen haben ein zusätzlichescapacity-Feld (int), das die Ladungsgröße in kg darstellt. Verwenden Siesuper, um die Initialisierung der Elternklasse zu handhaben. Implementieren Sie die Methodeoperate(), um Folgendes auszugeben:[brand] washing machine is washing [capacity]kg of clothesMicrowave.java: Erstellen Sie eine weitere konkrete Klasse, die Appliance erweitert. Mikrowellen haben einpower-Feld (int), das den Leistungspegel in Prozent darstellt. Implementieren Sieoperate(), um Folgendes auszugeben:[brand] microwave is heating at [power]% powerMain.java: Bringen Sie alles unter Verwendung von Polymorphismus zusammen. Sie erhalten fünf Eingaben: einen Markennamen, die Wattzahl, die Kapazität der Waschmaschine, einen weiteren Markennamen und den Leistungspegel der Mikrowelle. Erstellen Sie eine WashingMachine und eine Microwave und speichern Sie diese dann in einem Array vonAppliance-Referenzen. Durchlaufen Sie das Array in einer Schleife und geben Sie für jedes Gerät seine Informationen mitgetInfo()aus, gefolgt vom Aufruf vonoperate().
Sie erhalten fünf Eingaben in dieser Reihenfolge: erste Marke (String), erste Wattzahl (int), Kapazität in kg (int), zweite Marke (String) und Leistungspegel (int).
Ihre Ausgabe sollte vier Zeilen zeigen – für jedes Gerät sehen Sie seine Info-Zeile, gefolgt von seinem Betriebsverhalten. Beachten Sie, wie die abstrakte Klasse es Ihnen ermöglicht, verschiedene Geräte einheitlich zu behandeln, während jedes auf seine eigene, einzigartige Weise arbeitet!
Spickzettel
Eine abstrakte Klasse wird mit dem Schlüsselwort abstract deklariert und kann nicht direkt instanziiert werden. Sie dient als Bauplan für Unterklassen:
public abstract class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
// Abstrakte Methode - keine Implementierung
public abstract double getArea();
// Reguläre Methode - hat eine Implementierung
public String getColor() {
return color;
}
}Abstrakte Methoden haben keinen Rumpf und müssen von nicht-abstrakten Unterklassen implementiert werden:
public class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}Abstrakte Klassen können als Referenztypen für Polymorphismus verwendet werden:
Shape shape = new Circle("red", 5.0);
System.out.println(shape.getArea()); // Ruft die Implementierung von Circle aufAbstrakte Klassen sind ideal, wenn Unterklassen gemeinsamen Code teilen, aber bestimmte Verhaltensweisen unterschiedlich implementieren müssen.
Probier es selbst
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Eingaben lesen
String brand1 = scanner.nextLine();
int wattage1 = scanner.nextInt();
int capacity = scanner.nextInt();
scanner.nextLine(); // Zeilenumbruch konsumieren
String brand2 = scanner.nextLine();
int power = scanner.nextInt();
// TODO: Erstelle ein WashingMachine Objekt mit brand1, wattage1 und capacity
// TODO: Erstelle ein Microwave Objekt mit brand2, wattage1 (oder entsprechender Wattzahl) und power
// TODO: Erstelle ein Array von Appliance Referenzen und speichere beide Objekte
// TODO: Iteriere durch das Array und für jedes Gerät:
// - Gib seine Informationen mit getInfo() aus
// - Rufe operate() 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 this-SchlüsselwortMethodenFelder (Attribute)Konstruktor-MethodeKonstruktor-ÜberladungRückblick – Einfacher Taschenrechner4Vererbung
Grundlagen der Vererbung (extends)Das super-SchlüsselwortMethoden überschreiben (@Override)Konstruktor-VerkettungDie Object-KlasseEinfache & mehrstufige VererbungWarum keine Mehrfachvererbung von KlassenZusammenfassung - Mitarbeiter-Hierarchie7Spezielle Methoden & Object-Klasse
toString()-Methodeequals() und hashCode()clone()-MethodecompareTo() und ComparableComparator-InterfaceZusammenfassung – Benutzerdefiniertes Sortieren2Zugriffsmodifikatoren & Kapselung
Überblick über ZugriffsebenenGetter- und Setter-MethodenInformation HidingDas final-SchlüsselwortRückblick – Bankkonto-Manager5Polymorphismus
Grundlagen der MethodenüberladungMethodenüberschreibung (Laufzeit)Upcasting und DowncastingDer instanceof-OperatorAbstrakte Klassen und MethodenZusammenfassung – Formenrechner8Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungAggregation vs. KompositionInnere, geschachtelte & anonyme KlassenEnums und Enum-MethodenRecords (Java 16+)Sealed Classes (Java 17+)11Design Patterns Teil 1
Einführung in Design PatternsSingleton-PatternFactory-PatternBuilder-PatternObserver-PatternStrategy-Pattern14Abschlussherausforderungen
E-Learning-PlattformBanksystemSpielcharakter-EntwicklungFahrzeugvermietung3Klasseneigenschaften & Statische Member
Instanz- vs. statische VariablenStatische MethodenStatische BlöckeKonstanten (static final)Zusammenfassung – Zähler & Utility6Interfaces & Abstrakte Klassen
Einführung in InterfacesInterfaces implementierenImplementierung mehrerer InterfacesDefault- & statische Methoden in InterfacesAbstrakte Klassen vs. InterfacesFunktionale InterfacesZusammenfassung - Zahlungssystem