Programming lesson
Java-Klassen mit Objektbeziehungen: Ein Tutorial zu RetailItem und CashRegister
Lerne in diesem Tutorial, wie du in Java Klassen erstellst, die andere Objekte enthalten – am Beispiel eines Einzelhandelssystems mit RetailItem und CashRegister. Ideal für Studierende der Informatik.
Einführung in Objekte, die Objekte enthalten
In der objektorientierten Programmierung (OOP) ist es üblich, dass Klassen nicht nur primitive Datentypen wie int oder double speichern, sondern auch andere Objekte. Dieses Konzept wird oft als Komposition bezeichnet und ist essenziell für komplexe Anwendungen. In diesem Tutorial zeige ich dir Schritt für Schritt, wie du in Java eine Klasse CashRegister implementierst, die ein Objekt der Klasse RetailItem enthält. Dies ist eine typische Aufgabe im Modul ICS 141 – 02 und ähnelt vielen realen Systemen, zum Beispiel einem Warenkorbsystem in einem Online-Shop oder einer Inventarverwaltung in einem Supermarkt.
Warum ist das wichtig? Ein Trend-Beispiel aus der Gaming-Welt
Stell dir vor, du entwickelst ein Spiel wie Stardew Valley oder Animal Crossing, wo du Gegenstände sammelst und in deinem Inventar verwaltest. Jeder Gegenstand hat Eigenschaften wie Name, Anzahl und Wert. Wenn du einen Gegenstand an einen NPC verkaufst, muss eine Kasse die Transaktion abwickeln – genau das machen RetailItem und CashRegister in diesem Tutorial. Die Logik ist universell und kann auf viele Anwendungen übertragen werden.
Die RetailItem-Klasse: Grundbaustein des Systems
Die Klasse RetailItem repräsentiert einen einzelnen Artikel im Laden. Sie enthält drei Instanzvariablen:
- description: eine
String-Variable für die Artikelbeschreibung - unitsOnHand: ein
intfür den aktuellen Lagerbestand - price: ein
doublefür den Verkaufspreis in Dollar
Die Klasse stellt folgende Methoden bereit:
- Einen Konstruktor, der
descriptionundpriceinitialisiert undunitsOnHandauf 0 setzt. - Getter-Methoden für alle Instanzvariablen.
toString(): gibt eine formatierte Zeile mit allen Attributen zurück, getrennt durch Tabs.addUnits(int): fügt eine positive Anzahl zum Lagerbestand hinzu.getUnits(int): zieht eine Anzahl ab, wenn genügend Einheiten vorhanden sind; gibttrueoderfalsezurück.changePrice(double): ändert den Preis um einen positiven oder negativen Betrag, verhindert aber Preise ≤ 0.equals(Object): vergleicht zwei Artikel anhand von Beschreibung und Preis.totalValue(): berechnet den Gesamtwert (unitsOnHand * price).
Code-Beispiel für RetailItem
public class RetailItem {
private String description;
private int unitsOnHand;
private double price;
public RetailItem(String description, double price) {
this.description = description;
this.price = price;
this.unitsOnHand = 0;
}
// Getter
public String getDescription() { return description; }
public int getUnitsOnHand() { return unitsOnHand; }
public double getPrice() { return price; }
public String toString() {
return description + "\t" + unitsOnHand + "\t" + price;
}
public void addUnits(int units) {
if (units > 0) {
unitsOnHand += units;
}
}
public boolean getUnits(int quantity) {
if (quantity <= unitsOnHand) {
unitsOnHand -= quantity;
return true;
} else {
return false;
}
}
public void changePrice(double amount) {
if (price + amount > 0) {
price += amount;
} else {
System.out.println("Fehler: Neuer Preis wäre <= 0");
}
}
public boolean equals(Object obj) {
if (obj instanceof RetailItem) {
RetailItem other = (RetailItem) obj;
return this.description.equals(other.description) && this.price == other.price;
}
return false;
}
public double totalValue() {
return unitsOnHand * price;
}
}Die CashRegister-Klasse: Objektbeziehungen in der Praxis
Die Klasse CashRegister modelliert eine Kassen-Transaktion. Sie enthält drei Instanzvariablen:
- clerk: der Name des Mitarbeiters (String)
- item: das
RetailItem-Objekt, das verkauft wird - quantity: die Anzahl der zu verkaufenden Einheiten
Der Konstruktor nimmt diese drei Werte entgegen und ruft sofort item.getUnits(quantity) auf, um den Lagerbestand zu aktualisieren. Wichtig: Es wird angenommen, dass die übergebene Menge immer verfügbar ist.
Methoden der CashRegister-Klasse
- Getter für alle Instanzvariablen.
getSubTotal(): berechnet den Nettobetrag (quantity * price).getItemAvailability(): gibt die aktuell verfügbare Stückzahl des Artikels zurück.modifyQuantity(int): ändert die Verkaufsmenge und passt den Lagerbestand entsprechend an (positive Zahl = mehr verkaufen, negative = weniger).getTax(double taxRate): berechnet die Steuer auf den Nettobetrag.getTotal(double taxRate): gibt den Gesamtbetrag (Nettobetrag + Steuer) zurück.toString(): gibt eine formatierte Zeichenkette mit allen Details der Transaktion aus.
Code-Beispiel für CashRegister
public class CashRegister {
private String clerk;
private RetailItem item;
private int quantity;
public CashRegister(String clerk, RetailItem item, int quantity) {
this.clerk = clerk;
this.item = item;
this.quantity = quantity;
item.getUnits(quantity); // Lagerbestand reduzieren
}
// Getter
public String getClerk() { return clerk; }
public RetailItem getItem() { return item; }
public int getQuantity() { return quantity; }
public double getSubTotal() {
return quantity * item.getPrice();
}
public int getItemAvailability() {
return item.getUnitsOnHand();
}
public void modifyQuantity(int delta) {
if (delta > 0) {
// Mehr verkaufen: Lagerbestand reduzieren
if (item.getUnits(delta)) {
quantity += delta;
}
} else if (delta < 0) {
// Weniger verkaufen: Lagerbestand erhöhen
int absDelta = -delta;
item.addUnits(absDelta);
quantity -= absDelta;
}
}
public double getTax(double taxRate) {
return getSubTotal() * taxRate;
}
public double getTotal(double taxRate) {
return getSubTotal() + getTax(taxRate);
}
public String toString() {
return "Clerk: " + clerk + "\nItem: " + item.toString() + "\nQuantity: " + quantity + "\nSubtotal: " + getSubTotal();
}
}Die RetailStoreDriver-Klasse: Alles zusammenführen
Die RetailStoreDriver-Klasse enthält die main-Methode und testet die Funktionalität. Du erstellst zwei RetailItem-Objekte, fügst Einheiten hinzu, erzeugst einen CashRegister und rufst alle Methoden auf. Achte auf korrekte Formatierung und gib deinen Namen am Ende aus.
Beispiel für die Driver-Klasse
public class RetailStoreDriver {
public static void main(String[] args) {
RetailItem item1 = new RetailItem("Jacke", 59.54);
item1.addUnits(12);
System.out.println(item1.toString());
RetailItem item2 = new RetailItem("Hose", 39.99);
item2.addUnits(20);
CashRegister register = new CashRegister("Max Mustermann", item1, 3);
System.out.println(register.toString());
System.out.println("Steuer (5%): " + register.getTax(0.05));
System.out.println("Gesamt: " + register.getTotal(0.05));
// Teste modifyQuantity
register.modifyQuantity(2); // 2 weitere verkaufen
System.out.println("Nach Erhöhung: " + register.getQuantity());
System.out.println("Verfügbare Einheiten: " + register.getItemAvailability());
System.out.println("Programm erstellt von: Dein Name");
}
}Wichtige Hinweise für die Abgabe
- Achte auf exakte Methoden- und Variablennamen (Groß-/Kleinschreibung).
- Füge am Anfang jeder Java-Datei einen Kommentar mit deinem Namen, einer Beschreibung und dem Abgabedatum ein.
- Formatiere den Code konsistent: Einrückungen, geschweifte Klammern ausgerichtet.
- Teste alle Methoden gründlich, insbesondere Randfälle wie negative Preise oder zu große Mengen.
- Erstelle ein Video (max. 10 Minuten) mit deinem Gesicht, in dem du die Änderungen erklärst.
Fazit: Objektbeziehungen verstehen und anwenden
Mit diesem Tutorial hast du gelernt, wie du in Java Klassen erstellst, die andere Objekte enthalten. Das Konzept der Komposition ist grundlegend für viele Anwendungen – von einfachen Kassensystemen bis hin zu komplexen Spiele-Engines. Indem du RetailItem und CashRegister implementierst, schaffst du eine solide Basis für deine weiteren Programmierprojekte. Viel Erfolg bei deiner Abgabe!