Q1 OOP in Java

Das Telefonbuch: Klassen erstellen

Lösung geprüft

Die Aufgabe der heutigen Stunde sind die restlichen Telefonbuch-Klassen! Termin steht schon, jetzt kommen Kontakt, Adresse, Email, Telefon und Gruppe dazu. Das ist die größte Aufgabe des Projekts, aber vier der fünf Klassen sind nach demselben Muster gebaut wie Termin.

Die Aufgabenstellung lautet

Erstellen Sie alle weiteren Klassen. Kontakt ist die Klasse für das abgebildete Screenshot.

Die Klasse Adresse enthält die Adresse mit Straße, Hausnummer, PLZ, Ort und Land, außerdem wird der Typ gespeichert, ob die Adresse geschäftlich oder privat ist.

Die Klasse Email enthält die EMAIL, die als String gespeichert wird, und ebenfalls den Typ geschäftlich oder privat.

Die Klasse Telefon enthält die Telefonnummer, wird als String gespeichert und hat den Typ mobil oder Festnetz.

Die Zip-Datei beinhaltet die JAVA- und UML-Dateien zu: Kontakt, Telefon, Email, Adresse, Termin, Gruppe.

Drei der Klassen sind nach genau demselben Muster gebaut: ein Inhalt und dazu ein Typ, der die Auswahl aus dem Screenshot abbildet. Wenn du die drei nebeneinander siehst, wird das Muster offensichtlich:

classDiagram
    class Telefon {
        -String telefonnummer
        -Typ typ
    }
    class Email {
        -String email
        -Typ typ
    }
    class Adresse {
        -String strasse
        -String hausnummer
        -String plz
        -String ort
        -String land
        -Typ typ
    }
Telefon, Email und Adresse haben alle einen Typ

Lösungsprozess der Aufgabe

Kontakt · Adresse · Telefon · Email · Gruppe
/* meininfokurs.cmrg.site */
/**
 *
 * Die Klassen des Telefonbuchs
 * Jede Klasse gehoert in ihre eigene .java-Datei
 *
 * @version 1.0 vom 14.09.2025
 * @meininfokurs.cmrg.site
 */


// ============ Gruppe.java ============
public class Gruppe {

    private String name;

    public Gruppe(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return "Gruppe{name='" + name + "'}";
    }
}


// ============ Telefon.java ============
public class Telefon {

    public enum Typ { MOBIL, FESTNETZ }

    private String nummer;
    private Typ typ;

    public Telefon(String nummer, Typ typ) {
        this.nummer = nummer;
        this.typ = typ;
    }

    public String getNummer() {
        return nummer;
    }

    public void setNummer(String nummer) {
        this.nummer = nummer;
    }

    public Typ getTyp() {
        return typ;
    }

    public void setTyp(Typ typ) {
        this.typ = typ;
    }

    public String toString() {
        return "Telefon{nummer='" + nummer + "', typ=" + typ + "}";
    }
}


// ============ Email.java ============
public class Email {

    public enum Typ { PRIVAT, GESCHAEFTLICH }

    private String adresse;
    private Typ typ;

    public Email(String adresse, Typ typ) {
        this.adresse = adresse;
        this.typ = typ;
    }

    public String getAdresse() {
        return adresse;
    }

    public void setAdresse(String adresse) {
        this.adresse = adresse;
    }

    public Typ getTyp() {
        return typ;
    }

    public void setTyp(Typ typ) {
        this.typ = typ;
    }

    public String toString() {
        return "Email{adresse='" + adresse + "', typ=" + typ + "}";
    }
}


// ============ Adresse.java ============
public class Adresse {

    public enum Typ { PRIVAT, GESCHAEFTLICH }

    private String strasse;
    private String hausnummer;
    private String plz;
    private String ort;
    private String land;
    private Typ typ;

    public Adresse(String strasse, String hausnummer, String plz,
                   String ort, String land, Typ typ) {
        this.strasse = strasse;
        this.hausnummer = hausnummer;
        this.plz = plz;
        this.ort = ort;
        this.land = land;
        this.typ = typ;
    }

    public String getStrasse()     { return strasse; }
    public void setStrasse(String strasse) { this.strasse = strasse; }

    public String getHausnummer()  { return hausnummer; }
    public void setHausnummer(String hausnummer) { this.hausnummer = hausnummer; }

    public String getPlz()         { return plz; }
    public void setPlz(String plz) { this.plz = plz; }

    public String getOrt()         { return ort; }
    public void setOrt(String ort) { this.ort = ort; }

    public String getLand()        { return land; }
    public void setLand(String land) { this.land = land; }

    public Typ getTyp()            { return typ; }
    public void setTyp(Typ typ)    { this.typ = typ; }

    public String toString() {
        return "Adresse{" + "\n"
             + "strasse='" + strasse + "'" + "\n"
             + ", hausnummer='" + hausnummer + "'" + "\n"
             + ", plz='" + plz + "'" + "\n"
             + ", ort='" + ort + "'" + "\n"
             + ", land='" + land + "'" + "\n"
             + ", typ='" + typ + "'" + "\n"
             + "'}";
    }
}


// ============ Kontakt.java ============
import java.util.ArrayList;
import java.util.List;

public class Kontakt {

    // Anfang Attribute
    private String name;
    private Adresse adresse;
    private Telefon telefon;
    private Email email;
    private List<Termin> termine;
    private List<Gruppe> gruppen;
    // Ende Attribute

    // Konstruktor 1: nur der Name ist bekannt.
    // Die Listen werden trotzdem angelegt - leer, aber vorhanden.
    public Kontakt(String name) {
        this.name = name;
        this.termine = new ArrayList<Termin>();
        this.gruppen = new ArrayList<Gruppe>();
    }

    // Konstruktor 2: alles auf einmal
    public Kontakt(String name, Adresse adresse, Telefon telefon, Email email,
                   List<Termin> termine, List<Gruppe> gruppen) {
        this.name = name;
        this.adresse = adresse;
        this.telefon = telefon;
        this.email = email;
        this.termine = termine;
        this.gruppen = gruppen;
    }

    // Anfang Methoden
    public String getName()        { return name; }
    public void setName(String name) { this.name = name; }

    public Adresse getAdresse()    { return adresse; }
    public void setAdresse(Adresse adresse) { this.adresse = adresse; }

    public Telefon getTelefon()    { return telefon; }
    public void setTelefon(Telefon telefon) { this.telefon = telefon; }

    public Email getEmail()        { return email; }
    public void setEmail(Email email) { this.email = email; }

    public List<Termin> getTermine() { return termine; }
    public void setTermine(List<Termin> termine) { this.termine = termine; }

    public void fuegeTerminHinzu(Termin termin) {
        termine.add(termin);
    }

    public boolean entferneTermin(Termin termin) {
        return termine.remove(termin);
    }

    public List<Gruppe> getGruppen() { return gruppen; }
    public void setGruppen(List<Gruppe> gruppen) { this.gruppen = gruppen; }

    public void fuegeGruppeHinzu(Gruppe gruppe) {
        gruppen.add(gruppe);
    }

    public String toString() {
        String ausgabe = "=== Kontakt ===" + "\n"
                       + "Name    : " + name + "\n"
                       + adresse + "\n\n"
                       + "Telefon : " + telefon + "\n"
                       + "E-Mail  : " + email + "\n\n"
                       + "=== Termine ===" + "\n";
        for (Termin t : termine) {
            ausgabe += t + "\n";
        }
        ausgabe += "\n=== Gruppen ===" + "\n";
        for (Gruppe g : gruppen) {
            ausgabe += g + "\n";
        }
        return ausgabe;
    }
    // Ende Methoden

} // end of class Kontakt

In der Aufgabenstellung wird gefordert, dass wir folgende Sachen umsetzen:

  1. Fünf Klassen anlegen: Kontakt, Adresse, Telefon, Email, Gruppe
  2. Jede bekommt ihre Attribute, Getter und Setter
  3. Telefon, Email und Adresse bekommen einen Typ als enum
  4. Kontakt bekommt Listen für Termine und Gruppen
  5. Jede Klasse bekommt eine toString()

Kontakt ist die Klammer um alles

Vier der fünf Klassen sind unspektakulär: ein paar Strings, ein enum, Getter, Setter, toString(). Interessant ist nur Kontakt, weil dort die anderen als Attribute auftauchen:

private Adresse adresse;          // ein Objekt, kein String
private Telefon telefon;
private Email email;
private List<Termin> termine;     // mehrere Objekte
private List<Gruppe> gruppen;

Das ist genau der Punkt, um den es in dem ganzen Kapitel geht. Eine Klasse darf als Attribut andere Klassen haben. Damit entstehen die Beziehungen, die im UML-Diagramm als Striche auftauchen.

Warum List und nicht ArrayList

Im UML steht termine: List<Termin> und nicht ArrayList<Termin>. Der Unterschied:

private List<Termin> termine;                       // der Typ des Attributs
this.termine = new ArrayList<Termin>();            // was tatsaechlich drin liegt

List ist die allgemeinere Bezeichnung – „irgendeine Liste". ArrayList ist eine bestimmte Sorte davon. Links den allgemeinen Typ zu schreiben und rechts den konkreten ist üblich: wenn du später merkst, dass eine LinkedList besser passt, musst du nur die eine Zeile mit new ändern. Der Rest der Klasse bleibt gleich.

Erinnere dich an die Hierarchie aus dem ArrayList-Kapitel: Collection ganz oben, darunter List, und darunter ArrayList und LinkedList. Wir nehmen bewusst die mittlere Ebene.

Die Listen im Konstruktor anlegen

Das ist der Fehler, den man bei dieser Aufgabe garantiert einmal macht. Konstruktor 1 bekommt nur den Namen – trotzdem werden die beiden Listen dort angelegt:

public Kontakt(String name) {
    this.name = name;
    this.termine = new ArrayList<Termin>();     // NICHT weglassen
    this.gruppen = new ArrayList<Gruppe>();
}

Lässt du die zwei Zeilen weg, sind termine und gruppen nicht etwa leere Listen, sondern null – also gar keine Liste. Beim ersten fuegeTerminHinzu(...) fliegt dir dann eine NullPointerException um die Ohren, und die Fehlermeldung zeigt auf termine.add(termin), obwohl der Fehler im Konstruktor sitzt. Solche Fehler sucht man ewig.

Merksatz: Listen-Attribute werden immer im Konstruktor angelegt, auch wenn sie leer bleiben. Eine leere Liste ist etwas völlig anderes als keine Liste.

fuegeTerminHinzu statt setTermine

Im UML stehen für die Termine gleich drei Methoden: setTermine, fuegeTerminHinzu und entferneTermin. Warum nicht nur der Setter?

Weil setTermine die ganze Liste ersetzt. Wer einen einzelnen Termin hinzufügen will, müsste sich erst die Liste holen, etwas anhängen und sie zurückschreiben. Mit fuegeTerminHinzu ist das eine Zeile – und vor allem kann man in der Methode noch prüfen, ob der Termin überhaupt sinnvoll ist.

entferneTermin gibt einen boolean zurück. Das kommt direkt von List.remove(): true, wenn etwas entfernt wurde, false, wenn der Termin gar nicht drin war. So kann der Aufrufer reagieren, statt im Dunkeln zu tappen.

Drei Klassen, drei enums namens Typ

Telefon.Typ hat MOBIL und FESTNETZ, Email.Typ und Adresse.Typ haben PRIVAT und GESCHAEFTLICH. Alle drei heißen Typ – das geht, weil sie jeweils innerhalb ihrer Klasse stehen. Der volle Name ist Telefon.Typ beziehungsweise Email.Typ, und damit sind sie eindeutig unterscheidbar.

new Telefon("+49 611 123456", Telefon.Typ.FESTNETZ);
new Email("info@muster.de", Email.Typ.GESCHAEFTLICH);

Und weil es eigene enums sind, kann man auch nicht aus Versehen Telefon.Typ.PRIVAT schreiben – das gibt es nicht, und der Compiler sagt es dir sofort.

Aufgabe suchen

Tippe los. Strg+K öffnet die Suche von überall.

Zuletzt angesehen

Werbung