Zurück zur StartseiteInformatik · Q1 Grundkurs · Fach wechseln
Kostenlos starten
Q1 Grundkurs · Informatik
Datenbanken, Datenstrukturen und Automaten in der Qualifikationsphase · Objektorientierung, Datenstrukturen und Algorithmen

Klassen, Vererbung und UML

Die Stadt Köln plant eine Verkehrssimulation: Autos, Busse und Fahrräder sollen sich über einen Stadtplan bewegen. Jedes Fahrzeug hat eine Position und eine Geschwindigkeit, aber jedes bewegt sich anders. Wie baust du ein Programm, in dem du nicht für jedes Fahrzeug alles neu schreiben musst und trotzdem neue Fahrzeugtypen leicht ergänzen kannst? Genau dafür gibt es die Objektorientierung.

Klassen und Objekte

Eine Klasse ist ein Bauplan. Sie beschreibt, welche Attribute (Eigenschaften) und welche Methoden (Fähigkeiten) Dinge einer Art haben. Ein Objekt ist ein konkretes Exemplar nach diesem Bauplan, mit eigenen Attributwerten (Zustand).

In UML (Unified Modeling Language) zeichnest du eine Klasse als Rechteck mit drei Abschnitten: Name, Attribute, Methoden.

UML-Klassendiagramm der Klasse Fahrrad und ein Objekt dieser Klasse Fahrrad - farbe : String - gaenge : int + schalte(g : int) : void Objekt mein_rad : Fahrrad farbe = "rot" gaenge = 21

- bedeutet private, + bedeutet public. Der Objektname im Objektdiagramm wird unterstrichen geschrieben; hier steht er der Einfachheit halber im Kopf des Kastens.

In Java erzeugst du ein Objekt mit new. Der Konstruktor setzt die Anfangswerte:

public class Fahrrad {

    private String farbe;

    private int gaenge;

    public Fahrrad(String farbe, int gaenge) {

        this.farbe = farbe;

        this.gaenge = gaenge;

    }

}

// Fahrrad meinRad = new Fahrrad("rot", 21);
Üben★☆☆Nicht begonnen
Eine Klasse Fahrrad hat die Attribute farbe (String) und gaenge (int) sowie die Methode schalte(int g). a) Zeichnen Sie das UML-Klassendiagramm (als Text mit drei…

Eine Klasse Fahrrad hat die Attribute farbe (String) und gaenge (int) sowie die Methode schalte(int g).

  1. a) Zeichnen Sie das UML-Klassendiagramm (als Text mit drei Abschnitten).
  1. b) Erklären Sie den Unterschied zwischen Klasse und Objekt und geben Sie ein Beispielobjekt an.
Lösen

Kapselung: private und public

Würde jeder von außen direkt an stand eines Kontos schreiben, könnte jemand den Kontostand auf einen unsinnigen Wert setzen. Deshalb gilt das Geheimnisprinzip (Kapselung):

  • private: Zugriff nur innerhalb der eigenen Klasse.

  • public: Zugriff von überall.

Attribute sind meist private. Der Zugriff läuft über öffentliche Methoden: Getter (lesen) und Setter oder andere Methoden (ändern), die Bedingungen prüfen.

Üben★☆☆Nicht begonnen
Gegeben ist die Klasse a) Erklären Sie die Bedeutung von private und public. b) Ergänzen Sie eine Methode einzahlen(double betrag), die nur positive Beträge akzeptiert.

Gegeben ist die Klasse

public class Konto {

    private double stand;

    public double getStand() { return stand; }

}
  1. a) Erklären Sie die Bedeutung von private und public.
  1. b) Ergänzen Sie eine Methode einzahlen(double betrag), die nur positive Beträge akzeptiert.
Lösen

Vererbung und abstrakte Klassen

Hunde und Katzen sind beide Tiere: Sie haben einen Namen und ein Alter. Statt das zweimal zu schreiben, legst du die gemeinsamen Teile in eine Oberklasse (Tier). Die Unterklassen Hund und Katze erben alles und ergänzen Eigenes. Es gilt die „ist-ein“-Beziehung: Ein Hund ist ein Tier.

Vererbungsdiagramm: Die Klassen Hund und Katze erben von Tier Tier - name : String - alter : int Hund + belle() : void Katze + miaue() : void

Der Pfeil mit dem leeren Dreieck zeigt immer auf die Oberklasse. In Java schreibst du extends und rufst den Konstruktor der Oberklasse mit super auf:

public class Medium {

    protected String titel;

    protected String signatur;

    public Medium(String titel, String signatur) {

        this.titel = titel;

        this.signatur = signatur;

    }

}

public class Buch extends Medium {

    private int seitenzahl;

    public Buch(String titel, String signatur, int seitenzahl) {

        super(titel, signatur);

        this.seitenzahl = seitenzahl;

    }

}

protected erlaubt den Zugriff in der Klasse selbst und in ihren Unterklassen.

Eine abstrakte Klasse ist eine Oberklasse, von der es keine eigenen Objekte geben soll, etwa Form: Es gibt keine „Form an sich“, nur Kreise oder Quadrate. Sie darf abstrakte Methoden enthalten, die nur einen Kopf, aber keinen Rumpf haben. Jede nicht abstrakte Unterklasse muss sie ausprogrammieren. new Form() ist verboten, weil unklar wäre, was flaeche() berechnen soll.

Üben★☆☆Nicht begonnen
Die Klasse Tier hat die Unterklassen Hund und Katze. a) Zeichnen Sie das Vererbungsdiagramm. b) Erklären Sie, was Vererbung bedeutet, und nennen Sie ein Attribut, das in…

Die Klasse Tier hat die Unterklassen Hund und Katze.

  1. a) Zeichnen Sie das Vererbungsdiagramm.
  1. b) Erklären Sie, was Vererbung bedeutet, und nennen Sie ein Attribut, das in Tier stehen sollte.
Lösen
Üben★★☆Nicht begonnen
Eine Bibliothek verwaltet Medien: Bücher (mit Seitenzahl) und DVDs (mit Spieldauer). Beide haben Titel und Signatur. a) Entwerfen Sie ein Klassendiagramm mit Oberklasse…

Eine Bibliothek verwaltet Medien: Bücher (mit Seitenzahl) und DVDs (mit Spieldauer). Beide haben Titel und Signatur.

  1. a) Entwerfen Sie ein Klassendiagramm mit Oberklasse Medium.
  1. b) Schreiben Sie die Java-Klassen Medium und Buch mit Konstruktoren (Aufruf super).
Lösen

Polymorphie und dynamisches Binden

Eine Variable vom Typ der Oberklasse darf auf Objekte von Unterklassen zeigen. Welche Methode bei einem Aufruf läuft, entscheidet erst zur Laufzeit der tatsächliche Objekttyp: dynamisches Binden. Das ist Polymorphie („Vielgestaltigkeit“): derselbe Aufruf, je nach Objekt anderes Verhalten.

Ein schwierigerer Fall: Eine Methode der Oberklasse ruft eine Methode auf, die in der Unterklasse überschrieben wurde.

class A { String wer(){ return "A"; }

          String hallo(){ return "Hallo " + wer(); } }

class B extends A { String wer(){ return "B"; } }

// A x = new B(); System.out.println(x.hallo());

hallo() wird von A geerbt, aber der Aufruf wer() geht an das tatsächliche Objekt, ein B. Ausgabe: „Hallo B“.

Wäre wer() in A private, könnte B sie weder sehen noch überschreiben. B.wer() wäre eine neue, unabhängige Methode. hallo() würde dann A.wer() nutzen: „Hallo A“.

Nutzen: Neue Unterklassen (z. B. Tretroller) lassen sich ergänzen, ohne dass der Code, der mit Form oder Fahrzeug arbeitet, geändert wird. Die Software ist leichter erweiterbar und wartbar.

Üben★★☆Nicht begonnen
a) Erklären Sie, warum new Form() nicht erlaubt ist. b) Berechnen Sie die Summe der Flächen für Form[] f = { new Kreis(1), new Quadrat(2) }; auf zwei Nachkommastellen…
abstract class Form { abstract double flaeche(); }

class Kreis extends Form {

    double r;

    Kreis(double r){ this.r = r; }

    double flaeche(){ return Math.PI * r * r; }

}

class Quadrat extends Form {

    double a;

    Quadrat(double a){ this.a = a; }

    double flaeche(){ return a * a; }

}
  1. a) Erklären Sie, warum new Form() nicht erlaubt ist.
  1. b) Berechnen Sie die Summe der Flächen für Form[] f = { new Kreis(1), new Quadrat(2) }; auf zwei Nachkommastellen genau.
  1. c) Erläutern Sie, wo hier Polymorphie auftritt.
Lösen
Üben★★★Nicht begonnen
a) Geben Sie die Ausgabe von A x = new B(); System.out.println(x.hallo()); an und begründen Sie sie (dynamisches Binden). b) Erklären Sie, wie sich die Ausgabe ändert,…
class A { String wer(){ return "A"; } String hallo(){ return "Hallo " + wer(); } }

class B extends A { String wer(){ return "B"; } }
  1. a) Geben Sie die Ausgabe von A x = new B(); System.out.println(x.hallo()); an und begründen Sie sie (dynamisches Binden).
  1. b) Erklären Sie, wie sich die Ausgabe ändert, wenn wer() in A als private deklariert wäre, und warum B.wer() dann keine Überschreibung ist.
  1. c) Beurteilen Sie den Nutzen von Polymorphie für die Erweiterbarkeit von Software.
Lösen

Assoziationen und Multiplizitäten

Objekte stehen auch in Beziehung, ohne dass eine Vererbung vorliegt: Ein Kurs hat einen Lehrer und Schüler. Das ist eine Assoziation, eine Linie zwischen Klassen. An den Enden stehen Multiplizitäten: wie viele Objekte beteiligt sind (1, 0..1, * für beliebig viele, 1..*).

UML-Diagramm mit Vererbung von Schueler und Lehrer von Person und Assoziationen zu Kurs Person - name : String Schueler - klasse : String Lehrer - kuerzel : String Kurs * * 1 *

Lies die Multiplizitäten so: Die Assoziation Kurs–Lehrer hat am Lehrer die Multiplizität 1 (ein Kurs hat genau einen Lehrer) und am Kurs die Multiplizität * (ein Lehrer unterrichtet beliebig viele Kurse). Die Assoziation Kurs–Schueler hat an beiden Enden *: Ein Kurs hat viele Schüler, und ein Schüler besucht viele Kurse (n:m-Beziehung, denn in der Oberstufe wählt jeder Schüler mehrere Kurse).

In Java wird die Assoziation als Attribut umgesetzt: Bei Multiplizität 1 ein Attribut vom Typ der anderen Klasse, bei * eine Sammlung:

public class Kurs {

    private Lehrer lehrer;

    private ArrayList<Schueler> schueler = new ArrayList<>();

}
Üben★★☆Nicht begonnen
Ein Schulverwaltungsprogramm hat die Klassen Person (name), Schueler (klasse) und Lehrer (kuerzel). Ein Kurs hat genau einen Lehrer und viele Schüler. Ein Schüler kann…

Ein Schulverwaltungsprogramm hat die Klassen Person (name), Schueler (klasse) und Lehrer (kuerzel). Ein Kurs hat genau einen Lehrer und viele Schüler. Ein Schüler kann mehrere Kurse besuchen, und ein Lehrer kann mehrere Kurse unterrichten.

  1. a) Zeichnen Sie ein UML-Diagramm mit Vererbung und Assoziationen samt Multiplizitäten.
  1. b) Geben Sie an, wie die Assoziation Kurs–Schueler in Java als Attribut umgesetzt wird.
Lösen

Entwurf, Klassenbibliotheken und Testen

Zurück zur Kölner Verkehrssimulation: Alle Fahrzeuge haben Position und Geschwindigkeit und müssen sich bewegen, aber jede Art anders. Das ergibt eine abstrakte Oberklasse Fahrzeug mit der abstrakten Methode bewege(). Abstrakt ist bewege(), weil es für „ein Fahrzeug“ keine sinnvolle Bewegung gibt. Bus ergänzt Haltestellen.

public abstract class Fahrzeug {

    private double position;

    private double geschwindigkeit;

    public double getPosition() { return position; }

    protected void setPosition(double p) { position = p; }

    public double getGeschwindigkeit() { return geschwindigkeit; }

    public abstract void bewege();

}

public class Auto extends Fahrzeug {

    public void bewege() {

        setPosition(getPosition() + getGeschwindigkeit());

    }

}

Da die Attribute privat sind, kann nur die Klasse selbst Position und Geschwindigkeit ändern. Fehlerhafte Werte werden an einer Stelle abgefangen, und Fehler in der Simulation lassen sich schnell eingrenzen.

Klassenbibliotheken wie java.util.ArrayList<E> bieten fertige, getestete Klassen. Vorteile: weniger Programmieraufwand, weniger Fehler, einheitliche Schnittstellen, gute Dokumentation, hohe Wartbarkeit.

Systematisch testen heißt: vorher Testfälle mit erwarteten Ergebnissen festlegen und Normalfälle, Grenzfälle (leer, ein Element) und Sonderfälle abdecken. Dann Ergebnis und Erwartung vergleichen.

Üben★★★Nicht begonnen
Ein Verkehrssimulationsprogramm für Köln soll Fahrzeuge (Auto, Bus, Fahrrad) verwalten. Jedes Fahrzeug hat Position und Geschwindigkeit und muss sich in jedem…

Ein Verkehrssimulationsprogramm für Köln soll Fahrzeuge (Auto, Bus, Fahrrad) verwalten. Jedes Fahrzeug hat Position und Geschwindigkeit und muss sich in jedem Zeitschritt bewegen; die Bewegung unterscheidet sich je Typ. Busse halten zusätzlich an Haltestellen.

  1. a) Entwerfen Sie eine Klassenhierarchie mit abstrakter Oberklasse und begründen Sie, was abstrakt ist.
  1. b) Schreiben Sie Java-Code für die abstrakte Klasse und eine Unterklasse mit der Methode bewege().
  1. c) Begründen Sie, wie Kapselung (private Attribute, Getter) Fehler in der Simulation vermeiden hilft.
Lösen
Üben★★★Nicht begonnen
Gegeben ist die Klassenbibliothek java.util.ArrayList<Schueler>. Die Klasse Schueler besitzt eine Methode double getNote(). a) Schreiben Sie eine Methode double…

Gegeben ist die Klassenbibliothek java.util.ArrayList<Schueler>. Die Klasse Schueler besitzt eine Methode double getNote().

  1. a) Schreiben Sie eine Methode double durchschnitt(ArrayList<Schueler> liste), die den Durchschnitt von getNote() berechnet und den Fall der leeren Liste behandelt. Begründen Sie Ihre Entscheidung für das Verhalten bei leerer Liste (z. B. Rückgabewert $0{,}0$, Double.NaN oder Auslösen einer Ausnahme).
  1. b) Erläutern Sie Vorteile der Wiederverwendung von Klassenbibliotheken.
  1. c) Beschreiben Sie, wie Sie die Methode systematisch testen (mindestens vier Testfälle mit erwarteten Ergebnissen).
Lösen

Vor der Zusammenfassung zurück zum Anfang: Mit einer abstrakten Oberklasse Fahrzeug und der Methode bewege() kann die Simulation alle Fahrzeuge gleich behandeln. Neue Typen kommen als Unterklassen hinzu.

Auf einen Blick

  • Eine Klasse ist der Bauplan (Attribute, Methoden), ein Objekt ein Exemplar mit eigenem Zustand.

  • Kapselung: Attribute private, Zugriff über public Methoden mit Prüfungen.

  • Vererbung (extends, super) gilt bei „ist-ein“; abstrakte Klassen haben keine eigenen Objekte und schreiben Methoden vor.

  • Polymorphie: Das dynamische Binden wählt zur Laufzeit die Methode des tatsächlichen Objekts. Private Methoden werden nicht überschrieben.

  • Assoziationen werden mit Multiplizitäten (1, *, 0..1) modelliert und in Java als Attribute oder ArrayList umgesetzt.

  • Klassenbibliotheken sparen Aufwand; systematisches Testen nutzt Normal-, Grenz- und Sonderfälle.

Alle Aufgaben zu diesem Abschnitt anzeigen