103
Interface bzw. Schnittstelle anschaulich: Hüllenklasse

Interface bzw. Schnittstelle anschaulich: Hüllenklasse

  • Upload
    kaethe

  • View
    46

  • Download
    0

Embed Size (px)

DESCRIPTION

Interface bzw. Schnittstelle anschaulich: Hüllenklasse. - PowerPoint PPT Presentation

Citation preview

Page 1: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Interfacebzw.

Schnittstelle anschaulich:Hüllenklasse

Page 2: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Vorbemerkungenzur Mehrfachverebung.

Page 3: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Warum gibt es in Java keine Mehrfachvererbung? Dazu folgendes Beispiel:

OK1

K

+ f() : voidOK2

+ f() : void

OK1 und OK2 sind Oberklassen der Klasse K. In diesen Oberklassen befindet sich jeweils eine Methode mit dem Namen f().

Welche der 2 möglichen Methoden (blau oder rot) befindet sich in K ?

Da dies nicht eindeutig ist, wird in Java die Mehrfachvererbung verboten!

Page 4: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Ende der

Vorbemerkungen

Page 5: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Ein sogenanntes Konsolenprogramm gibt - im Gegensatz zu einer grafischen Oberfläche - mit System.out.println(...) seine Ausgabe auf dem Bildschirm aus.Ein Programmierer, der ein Konsolenprogramm schreibt und aufmerksam ist (d.h. das Programm auch testet), sollte folgendes beachten:

Page 6: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Jede Klasse sollte - zu Testzwecken - jeweils die Methode printAllAttributs() enthalten, mit der die Attribute einer Klasse auf dem Bildschirm ausgegeben werden. Um den Programmierer zu zwingen, diese Methode zu implementieren (auszuprogrammieren), könnte man sie (den Methodenkopf) in einer abstrakten Klasse ablegen.

Page 7: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier+ printAllAttributs(): void

Kuh+printAllAttributs():void

Henne+printAllAttributs():void

Abstrakte Klassen und Methoden werden durch eine kursive Schreibweise gekennzeichnet oder durch den Bezeichner {abstract}, siehe Präsentation zu abstrakte Klassen

Page 8: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Es ist aber nicht besonders sinnvoll printAllAttributs() als abstrakte Methode in die Klasse Nutztier zu stecken, da printAllAttributs() nicht speziell was mit der Klasse Nutztier zu tun hat, sondern in jeder Klasse vorkommt.

Page 9: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Es ist sinnvoller, diese Methode z.B. in eine mit Druckbar bezeichnete Klasse zu stecken und von dieser Klasse die Methode printAllAttributs() zu erben. Da es in Java keine Mehrfachvererbung gibt, (konkret: wenn z.B. Kuh Unterklasse von Nutztier ist, kann Kuh nicht auch noch Unterklasse von der Klasse Druckbar sein), hat man sich den Trick mit dem Interface einfallen lassen.

Page 10: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

In UML dargestelltergibt dies (siehe nächste Folie):

Bemerkung:Interfaces werden mit Hilfe von gestrichelten Linien dargestellt.Näheres siehe einige Folien weiter hinten.

Page 11: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier+printAllAttributs():void

Kuh+printAllAttributs():void

Henne+printAllAttributs():void

<<interface>>Druckbar

+ printAllAttributs(): voidMit Klasse statt

Interface hätte man eine Mehrfachvererbung

Page 12: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier+printAllAttributs():void

Kuh+printAllAttributs():void

Henne+printAllAttributs():void

<<interface>>Druckbar

+ printAllAttributs(): void

Page 13: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Eine Klasse kann beliebig viele Interfaces "einbinden" (mit dem Wort implements). Ein Interface ist ein Typ (so wie eine Klasse ein Typ ist), nur dass dort von den Methoden nur die Methodenköpfe (mit den Parametern) angegeben werden dürfen (wie bei abstrakten Klassen). Ein Interface ist von der Sache her abstract und es ist deswegen nicht nötig es (und seine Methoden) als abstract zu deklarieren.

Page 14: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Die komplette Methode (mit Methodenrumpf) muss dann in der Klasse ausprogrammiert werden, die dieses Interface (mit dem reservierten Wort implements) "einbindet".Ausnahme: In einer abstrakten Klasse müssen die Methoden des eingebundenen Interfaces nicht ausprogrammiert werden !Ein Interface besteht im Unterschied zu einer abstrakten Klasse nur aus Methodenköpfen (mit den Parametern).

Page 15: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Ein Interface muss in einer eigenen Datei erstellt werden, wenn es public ist (es gilt also das gleiche Schema wie bei Klassen: 2 public Klassen können nicht in der gleichen Datei sein).Ein Interface ist von der Sache her abstract und es ist deswegen nicht nötig es als abstract zu deklarieren (dies sollte auch nicht gemacht werden). In einem Interface dürfen nur Klassenvariable (mit public, static, final), aber keine "normalen" Attribute definiert werden.

Page 16: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Alle Methoden in Interfaces sind automatisch abstrakt und public. Deshalb sollten die Bezeichner public und abstract bei der Deklaration von Methoden in Interfaces nicht verwendet werden.

Dagegen müssen bei der Implementierung (Ausprogrammierung) einer Schnittstelle die Methoden in den Unterklassen mit public implementiert werden, da die Methoden in Interfaces immer automatisch public sind.

Page 17: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Bemerkung:

Ein StandardInterface ist ein Interface des Java-Systems, d.h. eines Interfaces das mit der Entwicklungsumgebung

ausgeliefert wird, wie z.B: Comparable, Serializable

Page 18: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Benennung von Interfaces:Zwar kann man (abgesehen von bestimmten Sonderzeichen) Interfaces benennen wie man will, doch könnte man folgenden Vorschlag berücksichtigen:

1)Interface endet mit ...bar bzw. auf englisch ...able Beispiel: PrintableDiese Begrifflichkeit ist dann analog zu StandardInterfaces wie Comparable, Serializable, usw.

Page 19: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

2)Interface beginnt mit I (wie Interface)

Beispiel: IKfzINutztier

Page 20: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Beispiel:(Wegen der übersichtlichen

Darstellung werden im Folgenden einige set- und

get-Methoden weggelassen)

Page 21: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Henne extends Nutztier implements Druckbar{ private double legeLeistung; public Henne(String pName, double pLegeLeistung){ super(pName); legeLeistung=pLegeLeistung; } public double getTierwert(){ return(2 * legeLeistung); } public void printAllAttributs(){ super.printAllAttributs(); System.out.println("Legelst.=" +legeLeistung); } }

Page 22: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Kuh extends Nutztier implements Druckbar{ private double milchLeistung; public Kuh(String pName, double pMilchLeistung){ super(pName); milchLeistung=pMilchLeistung; } public double getTierwert(){ return(100 * milchLeistung); } public void printAllAttributs(){ super.printAllAttributs(); System.out.println("Milchlst= " +milchLeistung); }}

Page 23: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

abstract class Nutztier implements Druckbar{ private String name; public Nutztier(String pName){ name = pName; } abstract public double getTierwert(); public double getGewinn(){ return(0.1*getTierwert()); } public void printAllAttributs(){ System.out.println("Name des Nutztiers = "+name); } }

Warum muß die Methode printAllAttributs() nicht

ausprogrammiert werden, obwohl die Klasse Nutztier das Interface

Druckbar einbindet?

Weil die Klasse abstrakt ist. Frage: Warum muß sie trotzdem ausprogrammiert werden?

Page 24: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

abstract class Nutztier implements Druckbar{ private String name; public Nutztier(String pName){ name = pName; } abstract public double getTierwert(); public double getGewinn(){ return(0.1*getTierwert()); } public void printAllAttributs(){ System.out.println("Name des Nutztiers = "+name); } }

In den Unterklassen wird mit super. printAllAttributs() die Methode printAllAttributs() der Oberklasse aufgerufen.

Page 25: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

public class MainInterface{ public static void main( String[] args){ Kuh myk=new Kuh("Elsa", 10); Henne myh=new Henne("Ute", 1); myk.printAllAttributs(); myh.printAllAttributs(); }}

Was wird auf dem Bildschirm ausgegeben ?

Page 26: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

public class MainInterface{ public static void main( String[] args){ Kuh myk=new Kuh("Elsa", 10); Henne myh=new Henne("Ute", 1); myk.printAllAttributs(); myh.printAllAttributs(); }}

Name der Nutztiers = ElsaMilchlst.= 10Name der Nutztiers = UteLegelst.= 1

Page 27: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

und hier das Interface:

Page 28: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

public interface Druckbar{ void printAllAttributs();}

Bezeichner abstract wird weggelassen

Bezeichner public und abstract werden weggelassen

Page 29: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Diskussion:Was soll das Interface?

Zu was braucht man hier das Interface?

Man kann es doch weglassen, und die Methode

printAllAttributs trotzdem verwenden, oder?

Page 30: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Das ist richtig!Deshalb gibt es nachher ein

Beispiel, das nicht ohne Interface auskommt !!!

Page 31: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Darstellung eines Interface in UML

Page 32: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

<<interface>>Druckbar

+ printAllAttributs(): void

Kuh+printAllAttributs():void

Henne+printAllAttributs():void

Ein Interface wird mit <<interface>> bezeichnet und mit einem Pfeil mit gestrichelten Linien auf das Interface gezeigt. Das Interface und die Methoden werden alle nicht kursiv geschrieben.

Page 33: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Hierarchie (Zuweisungskompatibilität)

Page 34: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

public class MainInterface{ public static void main( String[] args){ Kuh myk=new Kuh("Elsa", 10); Henne myh=new Henne("Ute", 1);

Druckbar aa1; Druckbar aa2; aa1 = myk; aa2 = myh; myh = aa2; myk = aa1; }}

Welche Anweisungen sind korrekt, welche falsch?

(Compiler meldet Fehler)

Diese 2 Anweisung sind falsch.

"Untertyp != Obertyp"

Diese 2 Anweisungen sind richtig:

"Obertyp = Untertyp"

// auch möglich:// Druckbar aa1 = myk;// Druckbar aa2 = myh;

Page 35: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Weiteres Beispiel:

Page 36: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Zusätzlich zu dem Beispiel mit den Nutztieren soll eine Klassenmethode void printObjekte(... feld) in der Klasse Bildschirmausgabeerstellt werden. Diese gibt alle Attribute der Objekte des Feldes feld auf Konsole aus, indem die obige Methode printAllAttributs() verwendet wird.

Page 37: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Da die Methode printObjekte(... feld) eine Klassenmethode ist, wird sie nicht durch ein Objekt aufgerufen, sondern durch den Klassennamen, also z.B:Bildschirmausgabe.printObjekte(feld);

Page 38: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Bildschirmausgabe{ public static void printObjekte(... feld){ ... }}

Da diese Methode eine Klassenmethode ist, muß sie den Bezeichner static haben

Welchen Typ (Datentyp) muss das Array feld haben? Wäre der Datentyp Henne sinnvoll?

Nein, denn die Methode soll für ein Array mit dem Datentyp Kuh oder Henne funktionieren.

Page 39: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Bildschirmausgabe{ public static void printObjekte(... feld){ ... }}

Wäre dann der Datentyp "Nutztier" sinnvoll?

Nein, denn die Methode soll für ein Array beliebigen Datentyps (nicht nur Kuh bzw. Henne) funktionieren.Sondern z.B. für beliebige (selbstgebastelte) Klassen, wie z.B. Auto, Kühlschrank, Buch, Blume, Mensch, ...

Da diese Methode eine Klassenmethode ist, muß sie den Bezeichner static haben

Page 40: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Bildschirmausgabe{ public static void printObjekte(... feld){ ... }}Ja, man muß nur bei Kuh und Henne (oder einer anderen Klasse) das Interface Druckbar implementieren, dann gilt:Kuh ist "Untertyp" vom Obertyp "Druckbar" Henne ist "Untertyp" vom Obertyp "Druckbar" Das Array feld muß also vom Typ "Druckbar" sein !

Kann man einen Datentyp angeben, den sowohl Kuh als auch Henne (als auch weitere selbstgebastelte Klassen) als "Oberdatentyp" besitzt?

Page 41: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Also wird die KlasseBildschirmausgabe

wie folgt implementiert:

Page 42: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Bildschirmausgabe{ public static void printObjekte( feld){ int i;

}}

for(i=0;i<feld.length;i++){ feld[i].printAllAttributs();}

Druckbar[]

In der Methode printObjekte(...) wird die Methode printAllAttributs(...) verwendet!Druckbar besitzt diese Methode, also hat feld den Datentyp Druckbar[]

Zwischenfrage: Muß feld (besser jedes Element davon) vom Datentyp Druckbar sein oder kann es auch ein Oberdatentyp davon sein wie z.B. Object, die Mutter aller Klassen, also ...

Page 43: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Bildschirmausgabe{ public static void printObjekte( feld){ int i;

}}

for(i=0;i<feld.length;i++){

feld[i] . printAllAttributs();}

Object[]

((Druckbar)

Da das übergebene Feldelement feld[i] die Methode printAllAttributs(...) verwendet, sollte (damit es keine Fehler gibt) feld[i] vom Datentyp Druckbar sein.

Da der Datentyp (Klasse) Object kein printAllAttributs(...) besitzt, muß also folgender Downcast gemacht werden ...

)

Page 44: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Frage:Muß Druckbar ein Interface sein, oder kann es auch eine abstrakte

Klasse oder einfach nur eine "einfache" Klasse sein?

Dazu schauen wir uns das UML-Diagramm an.

Page 45: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier+printAllAttributs():void

Kuh+printAllAttributs():void

Henne+printAllAttributs():void

<<interface>>Druckbar

+ printAllAttributs(): voidMit Klasse statt

Interface hätte man eine Mehrfachvererbung

also kann Druckbar keine Klasse bzw. abstrakte Klasse sein

Page 46: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Das gesamte Programm

(Klasse Henne, Kuh, Nutztier ähnlich wie oben; Klasse

Bildschirm kommt neu hinzu)

Page 47: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

package interface10;public class MainInterface10 { public static void main(String[] args){ Druckbar[] feld = new Druckbar[2]; Kuh myk=new Kuh("Elsa", 100); Henne myh=new Henne ("Frida", 1); feld[0] = myk; feld[1] = myh; Bildschirmausgabe.printObjekte(feld); }}

Page 48: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Nutztier implements Druckbar{ private String name;

public Nutztier(String pname){ name = pname; } public void printAllAttributs(){ System.out.println("Name des Nutztiers = "+name); }}

Klasse kann auch abstrakt sein. In diesem Zusammenhang ist dies völlig egal.

Aus Gründen einer einfachen Demonstration wurden in den Klassen Nutztier, Kuh und Henne einige Methoden (im Vergleich zum obigen Programm) weggelassen (wie z.B: getTierwert())

Page 49: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Kuh extends Nutztier implements Druckbar{ private double milchLeistung;

public Kuh(String pName, double pMilchLeistung){ super(pName); milchLeistung =pMilchLeistung; }

public void printAllAttributs(){ super.printAllAttributs(); System.out.println("Milchleistung= "+milchLeistung); }}

Page 50: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Henne extends Nutztier implements Druckbar{ private double legeLeistung; public Henne(String pName, double pLegeLeistung){ super(pName); legeLeistung =pLegeLeistung; }

public void printAllAttributs(){ super.printAllAttributs(); System.out.println("Legeleistung= "+legeLeistung); }}

Page 51: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Bildschirmausgabe{ public static void printObjekte(Druckbar[] feld){ int i; for(i=0;i<feld.length;i++){ feld[i].printAllAttributs(); } }}

Page 52: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

und hier das Interface:

Page 53: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

public interface Druckbar{ void printAllAttributs();}

Page 54: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Frage:Hätte man das Design des letzten Programms so abändern können,

daß Druckbar kein Interface, sondern eine Klasse bzw.

abstrakte Klasse sein kann, man also ohne Interface auskommt?

Page 55: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier+printAllAttributs():void

Kuh+printAllAttributs():void

Henne+printAllAttributs():void

Druckbar + printAllAttributs(): void

Druckbar ist hier kein Interface sondern eine Klasse

bzw. abstrakte KlasseWarum ist dieses Design schlecht?

Weil ein Nutztier inhaltlich betrachtet ...

kein Druckbar ist. Man kann zwar sagen:

Page 56: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier+printAllAttributs():void

Kuh+printAllAttributs():void

Henne+printAllAttributs():void

Druckbar + printAllAttributs(): voidEine Kuh ist ein Nutztier, aber es ist sinnlos zu sagen:

Ein Nutztier ist ein Druckbar. Selbst wenn man statt Druckbar einen besseren Namen wählt,

wie z.B. Drucker, gibt dies auch keinen Sinn!

Page 57: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

und hier das Programm:

Page 58: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

package ohneinterface10;public class MainOhneInterface10 { public static void main(String[] args){ Druckbar[] feld = new Druckbar[2]; Kuh myk=new Kuh("Elsa", 100); Henne myh=new Henne ("Frida", 1); feld[0] = myk; feld[1] = myh; Bildschirmausgabe.printObjekte(feld); }}

Warum ist dies erlaubt? Von einer "abstrakten Klasse", genauer einem Interface darf doch kein Objekt erzeugt werden!

Keine Änderung (im Vergleich zum letzten Programm)

Es werden keine Objekte erzeugt, sondern nur 2 Zeiger, die später auf Objekte zeigen.

Page 59: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Nutztier extends Druckbar { private String name;

public Nutztier(String pname){ name = pname; }

public void printAllAttributs(){ System.out.println("Name des Nutztiers = "+name); }}

implements Druckbar fehlt (im Vergleich zum letzten Programm)

Page 60: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Kuh extends Nutztier { private double milchLeistung; public Kuh(String pName, double pMilchLeistung){ super(pName); milchLeistung =pMilchLeistung; }

public void printAllAttributs(){ super.printAllAttributs(); System.out.println("Milchleistung= "+milchLeistung); }}

implements Druckbar fehlt (im Vergleich zum letzten Programm)

Page 61: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Henne extends Nutztier { private double legeLeistung; public Henne(String pName, double pLegeLeistung){ super(pName); legeLeistung =pLegeLeistung; }

public void printAllAttributs(){ super.printAllAttributs(); System.out.println("Legeleistung= "+legeLeistung); }}

implements Druckbar fehlt (im Vergleich zum letzten Programm)

Page 62: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Bildschirmausgabe{ public static void printObjekte(Druckbar[] feld){ int i; for(i=0;i<feld.length;i++){ feld[i].printAllAttributs(); } }}

Keine Änderung (im Vergleich zum letzten Programm)

Page 63: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Druckbar{public void printAllAttributs(){ System.out.println("schrott"); }

// public abstract void printAllAttributs();}

Druckbar ist jetzt kein Interface mehr, sondern eine Klasse (und hätte dann auch einen anderen (selbstsprechenden) Namen verdient).

Man könnte printAllAttributs() auch abstract machen und hätte dann eine abstrakte Klasse

Page 64: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Was fehlt jetzt noch?Ein Beispiel, wo man nicht auf ein Interface verzichten

kann.Können Sie so ein Beispiel

konstruieren?

Page 65: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Henne, Kuh und Krokodil (Fleisch, Leder) sind Nutztiere. Nur Kühe und Hennen können Freunde (zum Spielen) der Bauernkinder sein, nicht aber ein Krokodil (warum wohl?). Die Freunde machen Geschenke an die Bauernkinder:Kuh: Milchleistung / 2Henne: Legeleistung * 3

Kühe und Hennen spielen also die Rolle von Freunden.

Page 66: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Es sollen ein paar Freunde erstellt werden. Dann sollen die Geschenke dieser Freunde auf dem Bildschirm ausgegeben werden.

Aber zuerst das UML:

Page 67: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier

Kuh Henne Krokodil

Freund

+getGeschenk()

+getGeschenk()

+getGeschenk()

Dies ist der Ausgangspunkt: Kuh, Henne und Krokodil ist jeweils ein Nutztier. Wo benötigt man die Methode getGeschenk()?

Wie muß man Freund in dieses UML einfügen?

Wo gibt es Probleme?

Page 68: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier

Kuh Henne Krokodil

Freund

+getGeschenk()

+getGeschenk()

+getGeschenk()

Mit Klasse Freund hat man eine

Mehrfachvererbung

Was muß man also tun?

Aus Freund ein Interface machen!(mit dem

selbstsprechenden Namen IFreund)

Page 69: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier

Kuh Henne Krokodil

<<interface>> IFreund

+getGeschenk()

+getGeschenk()

+getGeschenk()

Was könnte man noch machen, damit der Programmierer gezwungen wird, die Methode printAllAttributs() zu implementieren?

Ein Interface wie Druckbar (oder mit einem anderen Namen wie IDruck) hinzuzufügen.

Page 70: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier

Kuh Henne Krokodil

<<interface>> IFreund

+getGeschenk()

+getGeschenk()

+getGeschenk()

<<interface>> IDruck

+printAllAttributs()

Page 71: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier

Kuh Henne Krokodil

<<interface>> IFreund

+getGeschenk()

+getGeschenk()

+getGeschenk()

<<interface>> IDruck

+printAllAttributs()

Sind die 4 grün bezeichneten "implements" Einbindungen redundant bzw. auf welche könnte man verzichten ?

Page 72: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier

Kuh Henne Krokodil

<<interface>> IFreund

+getGeschenk()

+getGeschenk()

+getGeschenk()

<<interface>> IDruck

+printAllAttributs()

Page 73: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier

Kuh Henne Krokodil

<<interface>> IFreund

+getGeschenk()

+getGeschenk()

+getGeschenk()

<<interface>> IDruck

+printAllAttributs()

oder auf welche könnte man alternativ noch verzichten ?

Page 74: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Nutztier

Kuh Henne Krokodil

<<interface>> IFreund

+getGeschenk()

+getGeschenk()

+getGeschenk()

<<interface>> IDruck

+printAllAttributs()

Page 75: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Und hier das Programm:

Page 76: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

package demointerface10;

public interface IDruck { void printAllAttributs();

}

Das Interface IDruck (in einer eigenen Datei)

Page 77: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

package interface20;

public interface IFreund { double getGeschenk(); void printGeschenk();}

Das Interface IFreund (in einer eigenen Datei)

Page 78: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

package interface20;public class MainInterface20 { public static void main(String[] args) { int i; IFreund freunde[] = new IFreund[4]; Nutztier[] nutztiere = new Nutztier[3];

nutztiere[0] = new Henne("Pute", 3); nutztiere[1] = new Henne("Elsa", 200); nutztiere[2] = new Krokodil("Schnappi", 50); freunde[0]= new Kuh("FreundMilka", 10); freunde[1]= new Henne("FreundUte", 5); freunde[2]= new Henne("FreundIda", 4); freunde[3]= new Kuh("FreundSusi", 34); for(i=0; i<freunde.length; i++){ freunde[i].printGeschenk(); } }}

"polymorphe Methode"

freunde[i] tritt verschiedengestaltig auf (als Henne oder Kuh)

Page 79: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

abstract class Nutztier implements IDruck{ private String name; public Nutztier(String pname) { name = pname; } abstract double getTierwert(); // Interface verlangt Implementierung public void printAllAttributs(){ System.out.println("Nutztier: "); }

public void setName(String pName) { name = pName; }

public String getName() { return (name); }}

Page 80: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Kuh extends Nutztier implements IFreund, IDruck { private double milchLeistung; public Kuh(String pName, double pMilchLeistung) { super(pName); milchLeistung = pMilchLeistung; }

public double getMilchLeistung() { return milchLeistung; }

public void setMilchLeistung(double milchLeistung) { this.milchLeistung = milchLeistung; }

Page 81: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

// abstrakte Klasse Nutztier verlangt // Implementierung public double getTierwert() { return (100 * milchLeistung); }

// Interface verlangt Implementierung public void printAllAttributs() { System.out.println("Kuhname=" + getName() + " Milchleistung=" + milchLeistung); }

Page 82: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

// Interface verlangt Implementierung public double getGeschenk() { return (milchLeistung / 2.0); }

// Interface verlangt Implementierung public void printGeschenk() { System.out.println("Kuhname= " + getName() + " Geschenk= " + getGeschenk()); }}

Page 83: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Henne extends Nutztier implements IFreund, IDruck { private int legeLeistung; public Henne(String pName, int pLegeLeistung) { super(pName); legeLeistung = pLegeLeistung; }

public int getLegeLeistung() { return legeLeistung; }

public void setLegeLeistung(int legeLeistung) { this.legeLeistung = legeLeistung; }

Page 84: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

// abstrakte Klasse Nutztier verlangt // Implementierung public double getTierwert() { return (2 * legeLeistung); }

// Interface verlangt Implementierung public void printAllAttributs() { System.out.println("Hennename=" + getName() + " Legeleistung=" + legeLeistung); }

Page 85: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

// Interface verlangt Implementierung public double getGeschenk() { return (3 * legeLeistung); }

// Interface verlangt Implementierung public void printGeschenk() { System.out.println("Hennename=" + getName() + " Geschenk=" + getGeschenk()); }}

Page 86: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Krokodil extends Nutztier implements IDruck { private int fleischmenge; public Krokodil(String pName, int pFleischmenge) { super(pName); fleischmenge = pFleischmenge; }

Page 87: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

// abstrakte Klasse Nutztier verlangt // Implementierung public double getTierwert() { return (20 * fleischmenge); }

// Interface verlangt Implementierung public void printAllAttributs() { System.out.println("Krokodilname=" + getName() + " Fleischmenge=" + fleischmenge); }}

Page 88: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Weitere Anwendung eines Interfaces

Page 89: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Aufgabe:Es sollen 3 Hunde (Objekte der Klasse Hund) nach deren Gewicht sortiert werden. Die Klasse Hund wird wie üblich (siehe früher) implementiert. Dies soll mit Hilfe von einigen Klassen bzw. Methoden der Entwicklungsumgebung realisiert werden. Dazu ...

Page 90: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

wird die Klassenmethode sort der Klasse Arrays verwendet.Diese sortiert ein Feld.

Wie heißt also der Aufruf, der die Hunde sortiert?

Page 91: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

public class Startklasse { public static void main(String[] args) { Hund[] hunde = new Hund[3]; hunde[0]=new Hund("Bello",30); hunde[1]=new Hund("Schnappi",20); hunde[2]=new Hund("Rex",10); Arrays.sort(hunde); for(int i=0;i<3;i++) System.out.println(hunde[i].getName()+ " "+hunde[i].getGewicht()); }}

Name eines Hundes

Gewicht eines Hundes

Page 92: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Warum geht dies:

Arrays.sort(hunde);

nicht so einfach?

Page 93: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Weil die Methode sort nicht weiß, nach welchem Kriterium (hier z.B. Gewicht) und wie (z.B. aufsteigend) sortiert werden soll.Diese Information muß also noch hinzugefügt werden. Dies wird hier so gemacht, daß die Klasse Hund die vom Programmierer ausprogrammierte Methode compareTo(...) enthalten muß.

Page 94: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Wie (mit welcher Technik) kann der Programmierer gezwungen werden, die Methode compareTo(...) selbst auszuprogrammieren?

Page 95: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Indem die Klasse Hund das von der Entwicklungsumgebung vorgegebene Interface Comparableeinbindet. Diese Interface Comparable enthält als Methodenkopf die Methode int compareTo(Object o)wobei (siehe Doku der Entwicklungsumgebung) Folgendes erfüllt sein muß:

Page 96: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Wennx. compareTo(y) <0 zurückliefert, dann ist x kleiner y0 zurückliefert, dann ist x == y>0 zurückliefert, dann ist x größer y

Page 97: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Schreiben Sie ein Java-Programm, das mit o.g. Mitteln die Hunde sortiert.

Page 98: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

package sortierenmitinterface1;import java.util.Arrays;

public class Startklasse { public static void main(String[] args) { Hund[] hunde = new Hund[3]; hunde[0]=new Hund("Bello",30); hunde[1]=new Hund("Schnappi",20); hunde[2]=new Hund("Rex",10); Arrays.sort(hunde); for(int i=0;i<3;i++) System.out.println(hunde[i].getName()+ " "+hunde[i].getGewicht()); }}

Page 99: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

class Hund implements Comparable { private String name; private double gewicht;

public Hund() { name = "Musterhund"; }

public Hund(String pName, double pGewicht) { name = pName; gewicht = pGewicht; }

public void setName(String n) { name = n; }

wie üblich (nichts besonderes)

Page 100: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

public String getName() { return (name); }

public void setGewicht(double pGewicht) { gewicht = pGewicht; }

public double getGewicht() { return (gewicht); }

wie üblich (nichts besonderes)

Page 101: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

public int compareTo(Object h){ if(this.gewicht<((Hund)h).gewicht) return -1; else if(this.gewicht==((Hund)h).gewicht) return 0; else return 1; }}

cast-Operator

Page 102: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

(Ein) Vorteil einer Schnittstelle

Page 103: Interface bzw. Schnittstelle  anschaulich: Hüllenklasse

Ein Programm kann multipersonal und flexibel entwickelt werden.Konkret am letzten Beispiel:Ein Programmierer (der Entwicklungsumgebung von Netbeans) entwickelt die Methode sort(...), ein anderer zeitgleich z.B. die Methode bestimmeMaximum(...).Sie müssen dabei nur die Methodenköpfe des Interfaces kennen, nicht deren Implementierung!