Assignment Chef icon Assignment Chef
All German tutorials

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.

Java Klassen Objektbeziehungen Java RetailItem CashRegister Tutorial ICS 141 Assignment 3 Java Komposition Objektorientierte Programmierung Java Java Einzelhandel Beispiel Java Lagerverwaltung Java Konstruktor mit Objektparameter Java toString Methode Java equals Methode Java Programmierung Studium Java Code Beispiel Java Objekte in Objekten Java Übungsaufgabe Einzelhandel

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 int für den aktuellen Lagerbestand
  • price: ein double für den Verkaufspreis in Dollar

Die Klasse stellt folgende Methoden bereit:

  • Einen Konstruktor, der description und price initialisiert und unitsOnHand auf 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; gibt true oder false zurü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!