studyklar
GdI 2 · Übungsblatt 6 · Aufgabe 1

Lieferungen mit Vererbung: Standard, Express, International

Eine Logistik-Software kennt drei Arten von Lieferungen. Alle haben Sendungsnummer, Adresse, Gewicht und Lieferdauer, aber jede hat eine Besonderheit. Mit Vererbung schreibt man das Gemeinsame nur einmal. Rechts steht das fertige Programm, die Zeilen zum aktuellen Schritt sind hervorgehoben. Mit Weiter geht es Schritt für Schritt voran.

Die Aufgabe

Aufgabe 1

Es sollen einige Klassen für eine Logistik-Software erstellt werden.

Jede Lieferung enthält eine Sendungsnummer (String), die Empfängeradresse (String), das Gewicht (double) und die Lieferdauer in Tagen (int). Zudem gibt es eine Methode zum Berechnen der Versandkosten und eine Methode, die die Lieferdauer zurückgibt. Die Lieferdauer ist standardmäßig 3 Tage. Die Versandkosten werden gemäß folgender Formel berechnet: Versandkosten = Grundpreis + (Gewicht * 0.5). Der Grundpreis beträgt derzeit 5 Euro.

Eine Standardlieferung enthält zusätzlich eine Methode zum Verschieben um eine bestimmte Zahl von Tagen. Hierdurch wird der Wert für die Lieferdauer entsprechend erhöht.

Bei einer Expresslieferung ist die Lieferdauer standardmäßig 1 Tag. Zudem enthält sie einen Expresszuschlag von standardmäßig 10 Euro. Die Berechnung der Gesamtkosten erfolgt gemäß der oben angegebenen Formel, zuzüglich dem Expresszuschlag.

Schließlich gibt es noch internationale Lieferungen, die zusätzlich zu allgemeinen Lieferungen ein Attribut für Zollgebühren haben. Zudem wird gespeichert, ob die Lieferung bereits vom Zoll abgefertigt wurde – was zu Beginn, beim Anlegen einer internationalen Lieferung noch nicht der Fall ist. Es gibt eine Methode, mit der man erfassen kann, dass die Zollabfertigung stattgefunden hat, und eine weitere Methode mit der man diese Information abfragen kann. Die Lieferdauer einer internationalen Lieferung ist 7 Tage. Die Versandkosten werden gemäß der obigen Formel berechnet, zuzüglich der Zollgebühren.

a) Erstellen Sie die oben angegebenen Klassen und nutzen Sie dabei die Vererbung. Schreiben Sie jeweils auch einen kanonischen Konstruktor mit Parametern für alle benötigten Werte.

b) Testen Sie Ihre Klassen. Legen Sie eine Standard-Lieferung an und geben Sie Versandkosten und Lieferdauer aus. Verschieben Sie sie anschließend um 2 Tage und geben Sie die geänderte Lieferdauer aus. Legen Sie eine internationale Lieferung an, geben Sie die Versandkosten aus, erfassen Sie die Zollabfertigung und zeigen Sie, dass sie erfasst wurde.

c) Ändern Sie die Formel für die Versandkosten auf: Grundpreis + (Gewicht * 0.7). Wenn Sie die Vererbung sinnvoll genutzt haben, muss nur an einer einzigen Stelle im Code eine Änderung durchgeführt werden.

Gesucht sind vier Klassen: eine allgemeine Lieferung und drei besondere Lieferungen. Dann testen wir zwei davon. Zum Schluss ändern wir die Kostenformel und prüfen, dass dafür eine einzige Zeile reicht.

Merke: Was alle Klassen gemeinsam haben, kommt in die Oberklasse. Eine Unterklasse erbt alles davon und schreibt nur das, was bei ihr anders oder neu ist.
  1. Das Gemeinsame finden und in die Oberklasse Lieferung schreiben.
  2. Die drei Unterklassen mit ihren Besonderheiten.
  3. Standardlieferung und internationale Lieferung testen.
  4. Die Formel an einer Stelle ändern.

Alle Klassen stehen hier in einer Datei LogistikAnwendung.java. Nur die Klasse mit main ist public; Java erlaubt höchstens eine öffentliche Klasse je Datei. In Eclipse darf jede Klasse auch eine eigene Datei bekommen, wie in der Musterlösung.

Das Gemeinsame finden

Klassehat zusätzlichLieferdauerVersandkosten
Lieferung (alle)Sendungsnummer, Adresse, Gewicht3 TageGrundpreis + Gewicht · 0,5
StandardLieferungMethode verschiebe3 Tagewie Lieferung
ExpressLieferungExpresszuschlag 10 Euro1 Tag+ Expresszuschlag
InternationaleLieferungZollgebühren, abgefertigt ja/nein, zwei Methoden7 Tage+ Zollgebühren

Bevor wir Code schreiben, sortieren wir den Aufgabentext. Die Tabelle zeigt, was jede Art von Lieferung hat. Die erste Zeile gilt für alle; sie wird die Oberklasse Lieferung. Die anderen Zeilen sind die Besonderheiten der Unterklassen.

Eine Unterklasse schreibt man mit extends: „StandardLieferung erweitert Lieferung“. Das heißt auch: Jede Standardlieferung ist eine Lieferung.

Aus Vorlesung 6, Folie 3 („Vererbung“): Die Oberklasse enthält das, was alle brauchen. Die Unterklassen sind Spezialfälle davon („ist ein“). Man sagt: Die Unterklasse erbt von der Oberklasse.

Die Attribute der Oberklasse

class Lieferung {    protected String sendungsnummer;    protected String empfaengerAdresse;    protected double gewicht;    protected int lieferdauer = 3;     protected static double grundpreis = 5.0;

Die vier Attribute jeder Lieferung stehen in Lieferung. Die Lieferdauer bekommt gleich den Startwert 3. Der Grundpreis ist static: Er gehört der Klasse, nicht jeder einzelnen Lieferung. So gibt es ihn nur einmal, und eine Preisänderung gilt sofort für alle.

Neu ist protected (geschützt) statt private. Bei private erben die Unterklassen die Attribute zwar, dürfen sie aber nicht direkt benutzen. Die Express- und die internationale Lieferung müssen aber lieferdauer ändern. protected erlaubt den Zugriff in der Klasse selbst und in allen Unterklassen.

Aus Vorlesung 6, Folie 4 („Was wird vererbt?“): Vererbt werden Attribute und Methoden. Was private ist, ist in der Unterklasse vorhanden, aber nicht direkt erreichbar; dafür gibt es protected.
Aus Vorlesung 5, Folie 25 („Klassenattribute und -methoden“): Ein static-Attribut gibt es einmal für die ganze Klasse, nicht einmal je Objekt.
Noch 8 Schritte bis zum Ergebnis
Den ganzen Lösungsweg sehen Studierende und Lehrende der HS KL. Registriere dich mit deiner Adresse @stud.hs-kl.de oder @hs-kl.de, dann geht es hier direkt weiter.

Das Programm LogistikAnwendung

vier Klassen und main

Abbildung 1Das Programm LogistikAnwendung

vier Klassen und main

class Lieferung {    protected String sendungsnummer;    protected String empfaengerAdresse;    protected double gewicht;    protected int lieferdauer = 3;     protected static double grundpreis = 5.0;     public Lieferung(String sendungsnummer, String empfaengerAdresse, double gewicht) {        this.sendungsnummer = sendungsnummer;        this.empfaengerAdresse = empfaengerAdresse;        this.gewicht = gewicht;    }     public double berechneVersandkosten() {        return grundpreis + (gewicht * 0.5);    }     public int getLieferdauer() {        return lieferdauer;    }} class StandardLieferung extends Lieferung {     public StandardLieferung(String sendungsnummer, String empfaengerAdresse, double gewicht) {        super(sendungsnummer, empfaengerAdresse, gewicht);    }     public void verschiebe(int tage) {        lieferdauer += tage;    }} class ExpressLieferung extends Lieferung {    private double expressZuschlag;     public ExpressLieferung(String sendungsnummer, String empfaengerAdresse, double gewicht) {        super(sendungsnummer, empfaengerAdresse, gewicht);        this.expressZuschlag = 10.0;        this.lieferdauer = 1;    }     @Override    public double berechneVersandkosten() {        return super.berechneVersandkosten() + expressZuschlag;    }} class InternationaleLieferung extends Lieferung {    private double zollgebuehren;    private boolean zollAbgefertigt = false;     public InternationaleLieferung(String sendungsnummer, String empfaengerAdresse,            double gewicht, double zollgebuehren) {        super(sendungsnummer, empfaengerAdresse, gewicht);        this.zollgebuehren = zollgebuehren;        this.lieferdauer = 7;    }     @Override    public double berechneVersandkosten() {        return super.berechneVersandkosten() + zollgebuehren;    }     public void erfasseZollabfertigung() {        zollAbgefertigt = true;    }     public boolean istZollAbgefertigt() {        return zollAbgefertigt;    }} public class LogistikAnwendung {     public static void main(String[] args) {         // Standard-Lieferung        StandardLieferung standard =                new StandardLieferung("SND12345", "Musterstraße 10, Berlin", 2.5);        System.out.println("Versandkosten Standardlieferung: " + standard.berechneVersandkosten());        System.out.println("Lieferdauer Standardlieferung: " + standard.getLieferdauer());        System.out.println("Verschiebe Standardlieferung um 2 Tage.");        standard.verschiebe(2);        System.out.println("Lieferdauer Standardlieferung: " + standard.getLieferdauer());         System.out.println();         // Internationale Lieferung        InternationaleLieferung international =                new InternationaleLieferung("INT12345", "Champs-Élysées 21, Paris", 5.0, 15.0);        System.out.println("Versandkosten internationale Lieferung: "                + international.berechneVersandkosten());        System.out.println("Ist die internationale Lieferung vom Zoll abgefertigt? "                + international.istZollAbgefertigt());        System.out.println("Erfasse Zollabfertigung für internationale Lieferung.");        international.erfasseZollabfertigung();        System.out.println("Ist die internationale Lieferung vom Zoll abgefertigt? "                + international.istZollAbgefertigt());    }}
LegendeDas ganze Programm.