Interfaces

== Interfaces

Unsere Zoohandlung erweitert ihr Sortiment. In den neuen Aquarien tummeln sich ab sofort viele Fische, die in unser Verwaltungsprogramm aufgenommen werden müssen.

Unsere Zoohandlung erweitert ihr Sortiment. In den neuen Aquarien tummeln sich ab sofort viele Fische, die in unser Verwaltungsprogramm aufgenommen werden müssen.

Ein Fisch ist natürlich ebenso ein Tier wie unser Löwe und der Papagei. Allerdings kann er nicht laufen, dafür aber schwimmen. Somit wäre ein denkbares UML-Diagramm für einen Fisch das folgende:

Ein Fisch ist natürlich ebenso ein Tier wie unser Löwe und der Papagei. Allerdings kann er nicht laufen, dafür aber schwimmen. Somit wäre ein denkbares UML-Diagramm für einen Fisch das folgende:

Im ersten Moment erscheint es sinnvoll, Fisch natürlich von Tier abzuleiten, also gemäß dem folgenden UML-Diagramm (wieder nur auf einige wesentliche Methoden und auf nur einen Konstruktor beschränkt):

Im ersten Moment erscheint es sinnvoll, Fisch natürlich von Tier abzuleiten, also gemäß dem folgenden UML-Diagramm (wieder nur auf einige wesentliche Methoden und auf nur einen Konstruktor beschränkt):

Das ging ja relativ einfach und schnell.

Aber Moment mal! Jetzt erbt die Klasse Fisch von der Elternklasse Tier das Feld anzahlBeine und die Methoden setAnzahlBeine und getAnzahlBeine! Das ergibt bei einem Fisch nicht wirklich Sinn. Natürlich könnten wir die Anzahl für einen Fisch auf 0 setzen, aber elegant ist das nicht.

Und es kommt noch schlimmer: Die Methode laufe wird gleichfalls von Tier geerbt. Somit könnte folgender Code eingegeben werden:

Das ging ja relativ einfach und schnell. Aber Moment mal! Jetzt erbt die Klasse _Fisch_ von der Elternklasse _Tier_ das Feld `anzahlBeine` und die Methoden `setAnzahlBeine` und `getAnzahlBeine`! Das ergibt bei einem Fisch nicht wirklich Sinn. Natürlich könnten wir die Anzahl für einen Fisch auf 0 setzen, aber elegant ist das nicht. Und es kommt noch schlimmer: Die Methode `laufe` wird gleichfalls von _Tier_ geerbt. Somit könnte folgender Code eingegeben werden:
Fisch f = new Fisch("Nemo",123);
f.laufe();
Java
[source,java,indent=0] ---- Fisch f = new Fisch("Nemo",123); f.laufe(); ----

Das sollte eigentlich gar nicht erst möglich sein. Ein Objekt vom Typ Fisch sollte nur den Zugriff auf sinnvolle Felder und Methoden erlauben.

Betrachten wir das an unserem Beispiel:

Wir wollen, dass nur Loewe und Papagei das Feld anzahlBeine haben und auch nur diese beiden Tiere sollen die zu Beinen passenden Methoden setAnzahlBeine(int anzahl), getAnzahlBeine() und laufe() zur Verfügung haben.

Die einfachste Lösung wäre die, diese Eigenschaften und Methoden wieder von Tier in Loewe und Papagei aufzunehmen, also für Papagei beispielsweise so:

Das sollte eigentlich gar nicht erst möglich sein. Ein Objekt vom Typ Fisch sollte nur den Zugriff auf sinnvolle Felder und Methoden erlauben. Betrachten wir das an unserem Beispiel: Wir wollen, dass nur _Loewe_ und _Papagei_ das Feld `anzahlBeine` haben und auch nur diese beiden Tiere sollen die zu Beinen passenden Methoden `setAnzahlBeine(int anzahl)`, `getAnzahlBeine()` und `laufe()` zur Verfügung haben. Die einfachste Lösung wäre die, diese Eigenschaften und Methoden wieder von _Tier_ in _Loewe_ und _Papagei_ aufzunehmen, also für _Papagei_ beispielsweise so:

Für Loewe würden wir analog vorgehen.

Ein Problem, das jetzt aber auftaucht: Beim Erstellen eines neuen Tiers muss der Programmierer darauf achten, dass in allen Tieren, die Beine haben, die Felder und Methoden gleich heißen.

Das wäre zum Beispiel dann sinnvoll, wenn man alle Tiere, die Beine haben, in einer Liste speichern möchte und mit Hilfe dieser Liste wieder die Anzahl der benötigten Pedikür-Kräfte berechnet. Das könnte so aussehen:

Für _Loewe_ würden wir analog vorgehen. Ein Problem, das jetzt aber auftaucht: Beim Erstellen eines neuen Tiers muss der Programmierer darauf achten, dass in allen Tieren, die Beine haben, die Felder und Methoden gleich heißen. Das wäre zum Beispiel dann sinnvoll, wenn man alle Tiere, die Beine haben, in einer Liste speichern möchte und mit Hilfe dieser Liste wieder die Anzahl der benötigten Pedikür-Kräfte berechnet. Das könnte so aussehen:
Tier[] tiere = new Tier[2]; // neues Array für zwei Objekte vom Typ Tier erstellen

Papagei p = new Papagei("Ara",1.3,"Hallo",40);
p.setAnzahlBeine(2);

Loewe leo = new Loewe("Leo",115);
leo.setAnzahlBeine(4);

tiere[0] = p; // p und leo im Array speichern
tiere[1] = leo;

int summe = 0; // in Summe steht am Ende die Gesamtzahl der Beine

for (int i = 0; i<tiere.length; i++) {
    summe += tiere[i].getAnzahlBeine(); // Problem!!
}
Java
[source,java,indent=0] ---- Tier[] tiere = new Tier[2]; // neues Array für zwei Objekte vom Typ Tier erstellen Papagei p = new Papagei("Ara",1.3,"Hallo",40); p.setAnzahlBeine(2); Loewe leo = new Loewe("Leo",115); leo.setAnzahlBeine(4); tiere[0] = p; // p und leo im Array speichern tiere[1] = leo; int summe = 0; // in Summe steht am Ende die Gesamtzahl der Beine for (int i = 0; i<tiere.length; i++) { summe += tiere[i].getAnzahlBeine(); // Problem!! } ----

Aber welche Überraschung: Wenn man diesen Code eingibt, muss man feststellen, dass das Programm so nicht compiliert! Wie ist das möglich?

Zunächst muss erwähnt werden, dass ein Array vom Typ Tier[] Objekte vom Typ Tier speichern kann. Ein Papagei und ein Löwe haben diese Eigenschaft: Ein Teil eines Objektes vom Typ Loewe ist vom Typ Tier, wie zum Beispiel das Feld name. Somit kann ein Array vom Typ Tier[] alle Objekte speichern, deren Typ von Tier abgeleitet wurde, also beispielsweise Objekte vom Typ Loewe oder Papagei.

In der vorletzten Zeile taucht das Problem auf: getAnzahlBeine() ist zwar in Loewe und Papagei vorhanden, jedoch nicht mehr in Tier. Somit könnte die vorletzte Zeile nur ausgeführt werden, wenn getAnzahlBeine() wieder in der Klasse Tier verortet wäre.

Aber dort haben wir diese Methode gerade erst herausgenommen, damit unser Fisch in die Hierarchie passt.

Eine unschöne Lösung, dieses Problem zu beheben, bestünde darin, in der for-Schleife eine Fallunterscheidung zu machen: der Befehl instanceof überprüft, ob ein Objekt von einem bestimmten Typ ist:

Aber welche Überraschung: Wenn man diesen Code eingibt, muss man feststellen, dass das Programm so nicht compiliert! Wie ist das möglich? Zunächst muss erwähnt werden, dass ein Array vom Typ `Tier[]` Objekte vom Typ _Tier_ speichern kann. Ein Papagei und ein Löwe haben diese Eigenschaft: Ein Teil eines Objektes vom Typ _Loewe_ ist vom Typ _Tier_, wie zum Beispiel das Feld *name*. Somit kann ein Array vom Typ `Tier[]` alle Objekte speichern, deren Typ von `Tier` abgeleitet wurde, also beispielsweise Objekte vom Typ _Loewe_ oder _Papagei_. In der vorletzten Zeile taucht das Problem auf: `getAnzahlBeine()` ist zwar in _Loewe_ und _Papagei_ vorhanden, jedoch nicht mehr in _Tier_. Somit könnte die vorletzte Zeile nur ausgeführt werden, wenn `getAnzahlBeine()` wieder in der Klasse _Tier_ verortet wäre. Aber dort haben wir diese Methode gerade erst herausgenommen, damit unser Fisch in die Hierarchie passt. Eine unschöne Lösung, dieses Problem zu beheben, bestünde darin, in der for-Schleife eine Fallunterscheidung zu machen: der Befehl `instanceof` überprüft, ob ein Objekt von einem bestimmten Typ ist:
for (int i = 0; i<tiere.length; i++) {
    if (tiere[i] instanceof Papagei){
        summe += ((Papagei) tiere[i]).getAnzahlBeine();
    } else if (tiere[i] instanceof Loewe){
        summe += ((Loewe) tiere[i]).getAnzahlBeine();
    }
}
Java
[source,java,indent=0] ---- for (int i = 0; i<tiere.length; i++) { if (tiere[i] instanceof Papagei){ summe += ((Papagei) tiere[i]).getAnzahlBeine(); } else if (tiere[i] instanceof Loewe){ summe += ((Loewe) tiere[i]).getAnzahlBeine(); } } ----

Hier wird also bei jedem Objekt, das im Array gespeichert ist, überprüft, ob es sich um ein Objekt vom Typ Papagei oder Loewe handelt, um dann das zugehörige Objekt vom Typ Tier zu einem Papagei oder Loewe zu casten, wodurch man auf die zugehörige Methode getAnzahlBeine() zugreifen kann.

Eine schreckliche Lösung! Wie wird das erst, wenn wir andere Tiere mit Beinen hinzunehmen?

Das ist so kompliziert, dass es wohl doch besser ist, getAnzahlBeine() und setAnzahlBeine in Tier zu lassen. Aber das war ja auch nicht gut …​

Oder gibt es eine bessere Lösung?

Hier wird also bei jedem Objekt, das im Array gespeichert ist, überprüft, ob es sich um ein Objekt vom Typ _Papagei_ oder _Loewe_ handelt, um dann das zugehörige Objekt vom Typ _Tier_ zu einem _Papagei_ oder _Loewe_ zu *casten*, wodurch man auf die zugehörige Methode `getAnzahlBeine()` zugreifen kann. Eine schreckliche Lösung! Wie wird das erst, wenn wir andere Tiere mit Beinen hinzunehmen? Das ist so kompliziert, dass es wohl doch besser ist, `getAnzahlBeine()` und `setAnzahlBeine` in _Tier_ zu lassen. Aber das war ja auch nicht gut ... Oder gibt es eine bessere Lösung?

Eine Lösung besteht nun darin, Interfaces einzuführen: Interfaces legen normalerweise konstante Felder und Methoden fest, ohne diese Methoden jedoch zu implementieren.

Eine Klasse kann nun ein oder mehrere Interfaces implementieren (also umsetzen), und muss dadurch alle Methoden, die ein Interface festlegt, enthalten und auch umsetzen.

Wie können wir das in unserem Beispiel verwenden?

Wir definieren ein Interface Laufen:

Eine Lösung besteht nun darin, *Interfaces* einzuführen: Interfaces legen normalerweise konstante Felder und Methoden fest, ohne diese Methoden jedoch zu implementieren. Eine Klasse kann nun *ein oder mehrere Interfaces* implementieren (also umsetzen), und *muss* dadurch *alle Methoden*, die ein Interface festlegt, enthalten und auch umsetzen. Wie können wir das in unserem Beispiel verwenden? Wir definieren ein Interface _Laufen_:

zoohandlung/Laufen.java:

package zoohandlung;

public interface Laufen {
    public void laufe();
    public int getAnzahlBeine();
    public void setAnzahlBeine(int anzahl);
}
Java
*zoohandlung/Laufen.java:* [source,java,indent=0] ---- package zoohandlung; public interface Laufen { public void laufe(); public int getAnzahlBeine(); public void setAnzahlBeine(int anzahl); } ----

Aus Tier entfernen wir laufe(), getAnzahlBeine() und setAnzahlBeine(int anzahl) ebenso wie das Feld anzahlBeine, da diese ja nur noch in Papagei und Loewe vorkommen sollen:

Aus _Tier_ entfernen wir `laufe()`, `getAnzahlBeine()` und `setAnzahlBeine(int anzahl)` ebenso wie das Feld `anzahlBeine`, da diese ja nur noch in _Papagei_ und _Loewe_ vorkommen sollen:

zoohandlung/Tier.java:

package zoohandlung;

public abstract class Tier {

    protected String name;
    double gewicht;
    String futterzeit;

    public Tier(){}

    public Tier(String name, double gewicht) {
        this.name = name;
        this.gewicht = gewicht;
    }

    @Override
    public String toString(){
        return "Ich heiße "+name+" und wiege "+gewicht+" kg";
    }
}
Java
*zoohandlung/Tier.java:* [source,java,indent=0] ---- package zoohandlung; public abstract class Tier { protected String name; double gewicht; String futterzeit; public Tier(){} public Tier(String name, double gewicht) { this.name = name; this.gewicht = gewicht; } @Override public String toString(){ return "Ich heiße "+name+" und wiege "+gewicht+" kg"; } } ----

Dafür setzen wir in Papagei und Loewe jeweils das Interface Laufen ein, was durch das Schlüsselwort implements verdeutlicht wird. Sobald implements in der Klassendefinition vorkommt, überprüft der Compiler, dass alle Methoden des Interfaces Laufen auch tatsächlich vorhanden sind, hier also laufe(), getAnzahlBeine() und setAnzahlBeine(int anzahl):

Dafür setzen wir in _Papagei_ und _Loewe_ jeweils das Interface _Laufen_ ein, was durch das Schlüsselwort `implements` verdeutlicht wird. Sobald `implements` in der Klassendefinition vorkommt, überprüft der Compiler, *dass alle Methoden des Interfaces _Laufen_ auch tatsächlich vorhanden sind*, hier also `laufe()`, `getAnzahlBeine()` und `setAnzahlBeine(int anzahl)`:

zoohandlung/Papagei.java:

package zoohandlung;

public class Papagei extends Tier implements Laufen {

    String lieblingswort;
    double spannweite;
    int anzahlBeine; // ist jetzt hier und nicht mehr in Tier

    public Papagei(String name, double gewicht, String lieblingswort, double spannweite) {
        super(name, gewicht);
        this.lieblingswort = lieblingswort;
        this.spannweite = spannweite;
    }

    public void fliege() {
        System.out.println("Ich fliege");
    }

    public String sprich(String wort) {
        System.out.println(wort);
        return wort;
    }

    @Override
    public void laufe() {
        System.out.println("Ich laufe");
    }

    @Override
    public void setAnzahlBeine(int anzahlBeine) {
        this.anzahlBeine = anzahlBeine;
    }

    @Override
    public int getAnzahlBeine() {
        return anzahlBeine;
    }
}
Java
*zoohandlung/Papagei.java:* [source,java,indent=0] ---- package zoohandlung; public class Papagei extends Tier implements Laufen { String lieblingswort; double spannweite; int anzahlBeine; // ist jetzt hier und nicht mehr in Tier public Papagei(String name, double gewicht, String lieblingswort, double spannweite) { super(name, gewicht); this.lieblingswort = lieblingswort; this.spannweite = spannweite; } public void fliege() { System.out.println("Ich fliege"); } public String sprich(String wort) { System.out.println(wort); return wort; } @Override public void laufe() { System.out.println("Ich laufe"); } @Override public void setAnzahlBeine(int anzahlBeine) { this.anzahlBeine = anzahlBeine; } @Override public int getAnzahlBeine() { return anzahlBeine; } } ----

Analog dazu wird auch die Klasse Loewe umgeschrieben:

Analog dazu wird auch die Klasse _Loewe_ umgeschrieben:

zoohandlung/Loewe.java:

package zoohandlung;

public class Loewe extends Tier implements Laufen {

    String maehnenShampooMarke;
    int anzahlBeine;

    public Loewe(String name, double gewicht) {
        this.name = name;
        this.gewicht = gewicht;
    }

    public Loewe(String name, double gewicht, String msm) {
        this.name = name;
        this.gewicht = gewicht;
        this.maehnenShampooMarke = msm;
    }

    public int bruelle(int dezibel) {
        System.out.println("Ich brülle mit " + " dB");
        return dezibel;
    }

    public void laufe() {
        System.out.println("Ich laufe");
    }

    public void setAnzahlBeine(int anzahlBeine) {
        this.anzahlBeine = anzahlBeine;
    }

    public int getAnzahlBeine() {
        return anzahlBeine;
    }
}
Java
*zoohandlung/Loewe.java:* [source,java,indent=0] ---- package zoohandlung; public class Loewe extends Tier implements Laufen { String maehnenShampooMarke; int anzahlBeine; public Loewe(String name, double gewicht) { this.name = name; this.gewicht = gewicht; } public Loewe(String name, double gewicht, String msm) { this.name = name; this.gewicht = gewicht; this.maehnenShampooMarke = msm; } public int bruelle(int dezibel) { System.out.println("Ich brülle mit " + " dB"); return dezibel; } public void laufe() { System.out.println("Ich laufe"); } public void setAnzahlBeine(int anzahlBeine) { this.anzahlBeine = anzahlBeine; } public int getAnzahlBeine() { return anzahlBeine; } } ----

Auf den ersten Blick sehen Loewe und Papagei so aus, als hätte man einfach nur alle Felder und Methoden, die mit Beinen zu tun haben, wieder in die einzelnen Klassen gezogen. Negativ fällt auf, dass laufe(), setAnzahlBeine(int anzahlBeine) und getAnzahlBeine in Loewe und Papagei vorkommen, und zwar identisch! Da haben wir wieder die doppelten Fehlerquellen!

Was aber haben wir gewonnen?

Kommen wir zurück zu unserem Pediküre-Beispiel:

Soeben hatten wir das Problem, dass beim Zusammenzählen der Fußanzahl in unserer Zoohandlung der Code-Abschnitt

Auf den ersten Blick sehen _Loewe_ und _Papagei_ so aus, als hätte man einfach nur alle Felder und Methoden, die mit Beinen zu tun haben, wieder in die einzelnen Klassen gezogen. Negativ fällt auf, dass `laufe()`, `setAnzahlBeine(int anzahlBeine)` und `getAnzahlBeine` in _Loewe_ und _Papagei_ vorkommen, und zwar identisch! Da haben wir wieder die doppelten Fehlerquellen! Was aber haben wir gewonnen? Kommen wir zurück zu unserem Pediküre-Beispiel: Soeben hatten wir das Problem, dass beim Zusammenzählen der Fußanzahl in unserer Zoohandlung der Code-Abschnitt
Tier[] tiere = new Tier[2]; // neues Array für zwei Objekte vom Typ Tier erstellen

Papagei p = new Papagei("Ara",1.3,"Hallo",40);
p.setAnzahlBeine(2);

Loewe leo = new Loewe("Leo",115);
leo.setAnzahlBeine(4);

tiere[0] = p; // p und leo im Array speichern
tiere[1] = leo;

int summe = 0; // in Summe steht am Ende die Gesamtzahl der Beine

for (int i = 0; i<tiere.length; i++) {
    summe += tiere[i].getAnzahlBeine(); // Problem!!
}
Java
[source,java,indent=0] ---- Tier[] tiere = new Tier[2]; // neues Array für zwei Objekte vom Typ Tier erstellen Papagei p = new Papagei("Ara",1.3,"Hallo",40); p.setAnzahlBeine(2); Loewe leo = new Loewe("Leo",115); leo.setAnzahlBeine(4); tiere[0] = p; // p und leo im Array speichern tiere[1] = leo; int summe = 0; // in Summe steht am Ende die Gesamtzahl der Beine for (int i = 0; i<tiere.length; i++) { summe += tiere[i].getAnzahlBeine(); // Problem!! } ----

zu dem Problem führte, dass getAnzahlBeine() zwar in Papagei und Loewe enthalten sind, nicht aber in Tier. tiere muss aber vom Typ Tier[] sein, damit darin Papageien und Löwen gespeichert werden können.

Wie hilft uns unter Interface Laufen bei der Lösung dieses Problems? Hier eine Möglichkeit:

zu dem Problem führte, dass `getAnzahlBeine()` zwar in _Papagei_ und _Loewe_ enthalten sind, nicht aber in _Tier_. `tiere` muss aber vom Typ `Tier[]` sein, damit darin Papageien und Löwen gespeichert werden können. Wie hilft uns unter Interface _Laufen_ bei der Lösung dieses Problems? Hier eine Möglichkeit:

externesPackage/ExterneMainKlasse.java:

package externesPackage;

import zoohandlung.*;

public class ExterneMainKlasse {

    public static void main(String[] args) {
        Laufen[] tiere = new Laufen[2]; // neues Array für zwei Objekte vom Typ Laufen erstellen

        Papagei p = new Papagei("Ara", 1.3, "Hallo", 40);
        p.setAnzahlBeine(2);

        Loewe leo = new Loewe("Leo", 115);
        leo.setAnzahlBeine(4);

        tiere[0] = p; // p und leo im Array speichern
        tiere[1] = leo;

        int summe = 0; // in Summe steht am Ende die Gesamtzahl der Beine

        for (int i = 0; i < tiere.length; i++) {
            summe += tiere[i].getAnzahlBeine(); // Jetzt geht alles!
        }
        System.out.println(summe);
    }
}
Java
*externesPackage/ExterneMainKlasse.java:* [source,java,indent=0] ---- package externesPackage; import zoohandlung.*; public class ExterneMainKlasse { public static void main(String[] args) { Laufen[] tiere = new Laufen[2]; // neues Array für zwei Objekte vom Typ Laufen erstellen Papagei p = new Papagei("Ara", 1.3, "Hallo", 40); p.setAnzahlBeine(2); Loewe leo = new Loewe("Leo", 115); leo.setAnzahlBeine(4); tiere[0] = p; // p und leo im Array speichern tiere[1] = leo; int summe = 0; // in Summe steht am Ende die Gesamtzahl der Beine for (int i = 0; i < tiere.length; i++) { summe += tiere[i].getAnzahlBeine(); // Jetzt geht alles! } System.out.println(summe); } } ----

Der Unterschied besteht darin, dass das Array tiere jetzt nicht mehr vom Typ Tier[] ist, sondern vom Typ Laufen[]. Somit kann dieses Array alle Objekte vom Typ Laufen speichern und auch alle Objekte, die das Interface Laufen implementieren!

Die Zeile in der for-Schleife macht nun keine Probleme mehr, da tiere[i] vom Typ Laufen ist: somit ist getAnzahlBeine() bekannt, da diese Methode im Interface Laufen zu finden ist.

Die Tatsache, dass ein Objekt vom Typ Papagei gleichzeitig auch ein Objekt vom Typ Tier und eines vom Typ Laufen ist wird als Polymorphismus ("Vielgestaltigkeit") bezeichnet.

Das Interface hat uns also dazu verholfen, dass unser Programm für alle Objekte vom Typ Laufen funktioniert. Kommt eine neue Tiersorte dazu, die Beine hat und das Interface Laufen implementiert, kann dieses auch im Array gespeichert und verarbeitet werden.

Der Vollständigkeit halber hier noch der Code von Fisch:

Der Unterschied besteht darin, dass das Array `tiere` jetzt nicht mehr vom Typ `Tier[]` ist, sondern vom Typ `Laufen[]`. Somit kann dieses Array alle Objekte vom Typ `Laufen` speichern *und auch alle Objekte, die das Interface Laufen implementieren!* Die Zeile in der for-Schleife macht nun keine Probleme mehr, da `tiere[i]` vom Typ `Laufen` ist: somit ist `getAnzahlBeine()` bekannt, da diese Methode im Interface _Laufen_ zu finden ist. [NOTE] ==== Die Tatsache, dass ein Objekt vom Typ _Papagei_ gleichzeitig auch ein Objekt vom Typ _Tier_ und eines vom Typ _Laufen_ ist wird als *Polymorphismus* ("Vielgestaltigkeit") bezeichnet. ==== Das Interface hat uns also dazu verholfen, dass unser Programm für alle Objekte vom Typ `Laufen` funktioniert. Kommt eine neue Tiersorte dazu, die Beine hat und das Interface _Laufen_ implementiert, kann dieses auch im Array gespeichert und verarbeitet werden. Der Vollständigkeit halber hier noch der Code von _Fisch_:

zoohandlung/Fisch.java:

package zoohandlung;

public class Fisch extends Tier {

    int maxTauchtiefe;
    int anzahlKiemen;

    public Fisch(String name, double gewicht) {
        super(name, gewicht);
    }

    public void schwimme() {
        System.out.println("Ich schwimme!");
    }

    public void blubber(int anzahl) {
        for (int i = 0; i < anzahl; i++) {
            System.out.println("blubb");
        }
    }
}
Java
*zoohandlung/Fisch.java:* [source,java,indent=0] ---- package zoohandlung; public class Fisch extends Tier { int maxTauchtiefe; int anzahlKiemen; public Fisch(String name, double gewicht) { super(name, gewicht); } public void schwimme() { System.out.println("Ich schwimme!"); } public void blubber(int anzahl) { for (int i = 0; i < anzahl; i++) { System.out.println("blubb"); } } } ----

Um Interfaces in UML darstellen zu können, werden gestrichelte Linien mit Pfeilspitzen für die Beziehungen verwendet, Interfaces selbst werden mit

<<interface>>

gekennzeichnet.

Das gesamte Klassendiagramm sieht nun so aus:

Um Interfaces in UML darstellen zu können, werden gestrichelte Linien mit Pfeilspitzen für die Beziehungen verwendet, Interfaces selbst werden mit ---- <<interface>> ---- gekennzeichnet. Das gesamte Klassendiagramm sieht nun so aus:

Gesamter Code dieses Kapitels

Den gesamten Code mit Klassendiagramm findest du hier.

Das komplette Netbeans-Projekt als Zip-Datei kannst du hier herunterladen:

=== Gesamter Code dieses Kapitels Den gesamten Code mit Klassendiagramm findest du <<tags_c,hier>>. Das komplette Netbeans-Projekt als Zip-Datei kannst du hier herunterladen:

Dateiname

Zoohandlung_Interfaces.zip

Größe in Bytes

18287

Einfügezeitpunkt

10.2.2018, 12:33:14

Zurück zur Einführung von Interfaces

<<tags_@,Zurück zur Einführung von Interfaces>>