Polymorphie/Späte Bindung Abstrakte Klassen Programmieren I Martin Schultheiß Hochschule Darmstadt – Wintersemester 2010/2011 Interfaces Polymorphie/Späte Bindung 1 Polymorphie/Späte Bindung 2 Abstrakte Klassen 3 Interfaces Abstrakte Klassen Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Definition: Polymorphie Der Begriff Polymorphie (manchmal auch exakter: Laufzeit-Polymorphie) bei der Ausführung von Methoden bedeutet: Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Definition: Polymorphie Der Begriff Polymorphie (manchmal auch exakter: Laufzeit-Polymorphie) bei der Ausführung von Methoden bedeutet: Es wird erst zur Laufzeit bestimmt wird, welche Implementierung für eine bestimmte Methode aufzurufen ist. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Definition: Polymorphie Der Begriff Polymorphie (manchmal auch exakter: Laufzeit-Polymorphie) bei der Ausführung von Methoden bedeutet: Es wird erst zur Laufzeit bestimmt wird, welche Implementierung für eine bestimmte Methode aufzurufen ist. Es kann also vom Programmablauf abhängig sein, aus welcher Klasse die Methode verwendet wird. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Definition: Polymorphie Der Begriff Polymorphie (manchmal auch exakter: Laufzeit-Polymorphie) bei der Ausführung von Methoden bedeutet: Es wird erst zur Laufzeit bestimmt wird, welche Implementierung für eine bestimmte Methode aufzurufen ist. Es kann also vom Programmablauf abhängig sein, aus welcher Klasse die Methode verwendet wird. Polymorphie ist ein wichtiger Bestandteil der objektorientierten Programmierung. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Definition: Polymorphie Der Begriff Polymorphie (manchmal auch exakter: Laufzeit-Polymorphie) bei der Ausführung von Methoden bedeutet: Es wird erst zur Laufzeit bestimmt wird, welche Implementierung für eine bestimmte Methode aufzurufen ist. Es kann also vom Programmablauf abhängig sein, aus welcher Klasse die Methode verwendet wird. Polymorphie ist ein wichtiger Bestandteil der objektorientierten Programmierung. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Definition: Polymorphie Der Begriff Polymorphie (manchmal auch exakter: Laufzeit-Polymorphie) bei der Ausführung von Methoden bedeutet: Es wird erst zur Laufzeit bestimmt wird, welche Implementierung für eine bestimmte Methode aufzurufen ist. Es kann also vom Programmablauf abhängig sein, aus welcher Klasse die Methode verwendet wird. Polymorphie ist ein wichtiger Bestandteil der objektorientierten Programmierung. Häufig wird Polymorphie als späte Bindung bezeichnet. Polymorphie/Späte Bindung Abstrakte Klassen Beispiel Betrachten wir als einfaches Beispiel die beiden folgenden (sinnlosen) Klassen: public c l a s s Basis { public int a = 1; } p u b l i c i n t getA ( ) { return a ; } Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Beispiel Betrachten wir als einfaches Beispiel die beiden folgenden (sinnlosen) Klassen: public c l a s s Basis { public int a = 1; } p u b l i c i n t getA ( ) { return a ; } public c l a s s Erweitert extends Basis { public int a = 2; } p u b l i c i n t getA ( ) { return a ; } Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Frage Welche Ausgabe ergibt folgendes Hauptprogramm? p u b l i c c l a s s Anwendung public s t a t i c void E r w e i t e r t e1 = B a s i s b1 = e1 ; B a s i s b2 = new { main ( S t r i n g [ ] a r g s ) { new E r w e i t e r t ( ) ; Basis ( ) ; System . out . p r i n t l n ( e1 . a ) ; System . out . p r i n t l n ( b1 . a ) ; System . out . p r i n t l n ( b2 . a ) ; } } System . out . p r i n t l n ( e1 . getA ( ) ) ; System . out . p r i n t l n ( b1 . getA ( ) ) ; System . out . p r i n t l n ( b2 . getA ( ) ) ; Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Analyse Bei den ersten drei Ausgabeanweisungen wird direkt auf das (öffentliche) Attribut a zugegriffen. Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Analyse Bei den ersten drei Ausgabeanweisungen wird direkt auf das (öffentliche) Attribut a zugegriffen. Hierbei gilt, dass anhand des Typs der Objektreferenz entschieden wird, aus welcher Klasse das Attribut a verwendet wird. Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Analyse Bei den ersten drei Ausgabeanweisungen wird direkt auf das (öffentliche) Attribut a zugegriffen. Hierbei gilt, dass anhand des Typs der Objektreferenz entschieden wird, aus welcher Klasse das Attribut a verwendet wird. Dies führt zu dem Effekt, dass e1 und b1 dasselbe Objekt referenzieren, jedoch die Ausdrücke e1.a und b1.a unterschiedliche Ergebnisse liefern, da e1 und b1 von verschiedenem Typ sind. Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Analyse Bei den ersten drei Ausgabeanweisungen wird direkt auf das (öffentliche) Attribut a zugegriffen. Hierbei gilt, dass anhand des Typs der Objektreferenz entschieden wird, aus welcher Klasse das Attribut a verwendet wird. Dies führt zu dem Effekt, dass e1 und b1 dasselbe Objekt referenzieren, jedoch die Ausdrücke e1.a und b1.a unterschiedliche Ergebnisse liefern, da e1 und b1 von verschiedenem Typ sind. In diesem Fall liegt schon zur Kompilierzeit fest, aus welcher Klasse a verwendet wird. Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Analyse Bei den ersten drei Ausgabeanweisungen wird direkt auf das (öffentliche) Attribut a zugegriffen. Hierbei gilt, dass anhand des Typs der Objektreferenz entschieden wird, aus welcher Klasse das Attribut a verwendet wird. Dies führt zu dem Effekt, dass e1 und b1 dasselbe Objekt referenzieren, jedoch die Ausdrücke e1.a und b1.a unterschiedliche Ergebnisse liefern, da e1 und b1 von verschiedenem Typ sind. In diesem Fall liegt schon zur Kompilierzeit fest, aus welcher Klasse a verwendet wird. Ausgabe also: 2 1 1 Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Analyse (Forts.) Bei Methoden in Java gilt das Prinzip der späten Bindung. Daher wird erst zur Laufzeit anhand der realen Instanz, auf die eine Referenz verweist, entschieden, aus welcher Klasse eine Methode benutzt wird. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Analyse (Forts.) Bei Methoden in Java gilt das Prinzip der späten Bindung. Daher wird erst zur Laufzeit anhand der realen Instanz, auf die eine Referenz verweist, entschieden, aus welcher Klasse eine Methode benutzt wird. Daher ergeben im Beispiel e1.getA() und b1.getA() dasselbe Resultat, da beide auf eine (sogar dieselbe) Instanz von Erweitert verweisen. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Analyse (Forts.) Bei Methoden in Java gilt das Prinzip der späten Bindung. Daher wird erst zur Laufzeit anhand der realen Instanz, auf die eine Referenz verweist, entschieden, aus welcher Klasse eine Methode benutzt wird. Daher ergeben im Beispiel e1.getA() und b1.getA() dasselbe Resultat, da beide auf eine (sogar dieselbe) Instanz von Erweitert verweisen. Demgegenüber unterscheiden sich b1.getA() und b2.getA(), obwohl beides Referenzen vom Typ Basis sind, da sie tatsächlich auf Instanzen verschiedener Klassen verweisen. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Analyse (Forts.) Bei Methoden in Java gilt das Prinzip der späten Bindung. Daher wird erst zur Laufzeit anhand der realen Instanz, auf die eine Referenz verweist, entschieden, aus welcher Klasse eine Methode benutzt wird. Daher ergeben im Beispiel e1.getA() und b1.getA() dasselbe Resultat, da beide auf eine (sogar dieselbe) Instanz von Erweitert verweisen. Demgegenüber unterscheiden sich b1.getA() und b2.getA(), obwohl beides Referenzen vom Typ Basis sind, da sie tatsächlich auf Instanzen verschiedener Klassen verweisen. Ausgabe also: 2 2 1 Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Praktisches Beispiel – Motivation Ein moderner Supermarkt besitzt Kassen, die sowohl scannen als auch wiegen können: Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Praktisches Beispiel – Motivation Ein moderner Supermarkt besitzt Kassen, die sowohl scannen als auch wiegen können: Normale Waren werden einzeln über den Scanner gezogen, und pro Stück der Einzelpreis zur Rechnungssumme addiert. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Praktisches Beispiel – Motivation Ein moderner Supermarkt besitzt Kassen, die sowohl scannen als auch wiegen können: Normale Waren werden einzeln über den Scanner gezogen, und pro Stück der Einzelpreis zur Rechnungssumme addiert. Bei Waren, die gewogen werden, wird der Kilopreis mit dem Gewicht der Ware (in kg) multipliziert und zur Rechnungssumme addiert. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Praktisches Beispiel – Motivation Ein moderner Supermarkt besitzt Kassen, die sowohl scannen als auch wiegen können: Normale Waren werden einzeln über den Scanner gezogen, und pro Stück der Einzelpreis zur Rechnungssumme addiert. Bei Waren, die gewogen werden, wird der Kilopreis mit dem Gewicht der Ware (in kg) multipliziert und zur Rechnungssumme addiert. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Praktisches Beispiel – Motivation Ein moderner Supermarkt besitzt Kassen, die sowohl scannen als auch wiegen können: Normale Waren werden einzeln über den Scanner gezogen, und pro Stück der Einzelpreis zur Rechnungssumme addiert. Bei Waren, die gewogen werden, wird der Kilopreis mit dem Gewicht der Ware (in kg) multipliziert und zur Rechnungssumme addiert. Es steht also fest: Jede Ware hat einen Preis, es hängt aber davon ab, ob es eine Stückware oder eine Gewichtsware ist, wie sich der Preis berechnet. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Implementierung – Klasse Ware Zunächst schaffen wir eine allgemeine Klasse Ware, die neben der Beschreibung der Ware erst einmal einen (noch unsinnigen) Preis hat: p u b l i c c l a s s Ware { private String beschreibung ; p u b l i c Ware ( S t r i n g b e s c h r e i b u n g ) { t h i s . beschreibung = beschreibung ; } public String getBeschreibung () { return beschreibung ; } } p u b l i c double g e t P r e i s ( ) { return 0; } Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Implementierung – Klasse StueckWare Nun kommt die Klasse StueckWare hinzu, bei der als Preis einfach der Stückpreis verwendet wird: p u b l i c c l a s s StueckWare e x t e n d s Ware { p r i v a t e double e i n z e l p r e i s ; p u b l i c StueckWare ( S t r i n g b e s c h r e i b u n g , d o u b l e e i n z e l p r e i s super ( beschreibung ) ; this . einzelpreis = einzelpreis ; } } @Override p u b l i c double g e t P r e i s ( ) { return e i n z e l p r e i s ; } Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Implementierung – Klasse GewichtsWare Nun die Klasse GewichtsWare hinzu, bei der Preis aus Gewicht und Kilopreis berechnet wird: p u b l i c c l a s s GewichtsWare e x t e n d s Ware { p r i v a t e double gewicht ; p r i v a t e double k i l o p r e i s ; p u b l i c GewichtsWare ( S t r i n g b e s c h r e i b u n g , d o u b l e gewicht , double k i l o p r e i s ) { super ( beschreibung ) ; t h i s . gewicht = gewicht ; this . kilopreis = kilopreis ; } } @Override p u b l i c double g e t P r e i s ( ) { return gewicht * k i l o p r e i s ; } Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Anwendung Somit kann für einen Array von Waren verschiedenen Typs einfach der Preis aufsummiert werden, da dynamisch entschieden wird, aus welcher Klasse getPreis verwendet wird: p u b l i c c l a s s Anwendung public s t a t i c void Ware [ ] waren = waren [ 0 ] = new waren [ 1 ] = new } } { main ( S t r i n g [ ] a r g s ) { new Ware [ 2 ] ; Stueckware ( " Chips " , 1 . 8 9 ) ; GewichtsWare ( " Rinderhack " , 6 . 9 9 , . 5 ) ; d o u b l e summe = 0 ; f o r ( Ware w : waren ) { summe += w . g e t P r e i s ( ) ; } System . out . p r i n t l n ( "Gesamtsumme : "+summe ) ; Polymorphie/Späte Bindung Abstrakte Klassen Kritikpunkte am Beispiel Das Beispiel dient zwar zur Demonstration der späten Bindung, allerdings gibt es zwei Kritikpunkte: Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Kritikpunkte am Beispiel Das Beispiel dient zwar zur Demonstration der späten Bindung, allerdings gibt es zwei Kritikpunkte: Es wäre möglich, im Beispiel Instanzen von Ware zu erzeugen, obwohl in der Realität nur Instanzen von StueckWare und GewichtsWare vorkommen sollen. Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Kritikpunkte am Beispiel Das Beispiel dient zwar zur Demonstration der späten Bindung, allerdings gibt es zwei Kritikpunkte: Es wäre möglich, im Beispiel Instanzen von Ware zu erzeugen, obwohl in der Realität nur Instanzen von StueckWare und GewichtsWare vorkommen sollen. In Ware ist die Methode getPreis mit sinnlosem Code definiert, nur damit sie dort schon bekannt ist (und für Referenzen vom Typ Ware benutzt werden kann). Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Abstrakte Klassen Klassen in Java können Methoden besitzen, die abstrakt sind. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Abstrakte Klassen Klassen in Java können Methoden besitzen, die abstrakt sind. Abstrakte Methoden besitzen nur einen (als abstrakt gekennzeichneten) Deklarationskopf, aber keinen Code. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Abstrakte Klassen Klassen in Java können Methoden besitzen, die abstrakt sind. Abstrakte Methoden besitzen nur einen (als abstrakt gekennzeichneten) Deklarationskopf, aber keinen Code. Klassen mit mindestens einer abstrakten Methode müssen als abstrakt markiert sein. Von abstrakten Klassen können keine Instanzen erzeugt werden. Polymorphie/Späte Bindung Abstrakte Klassen Neue Version der Klasse Ware p u b l i c a b s t r a c t c l a s s Ware { private String beschreibung ; p u b l i c Ware ( S t r i n g b e s c h r e i b u n g ) { t h i s . beschreibung = beschreibung ; } public String getBeschreibung () { return beschreibung ; } } p u b l i c a b s t r a c t double g e t P r e i s ( ) ; Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Manchmal implementieren abstrakte Klassen keinerlei Code, sondern deklarieren nur nach außen sichtbare Methoden. Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Manchmal implementieren abstrakte Klassen keinerlei Code, sondern deklarieren nur nach außen sichtbare Methoden. Für solche Zwecke gibt es in Java ein spezielles Sprachelement, die so genannten Interfaces. Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Manchmal implementieren abstrakte Klassen keinerlei Code, sondern deklarieren nur nach außen sichtbare Methoden. Für solche Zwecke gibt es in Java ein spezielles Sprachelement, die so genannten Interfaces. Ein Interface wird in Java wie eine Klasse definiert (nur mit dem Schlüsselwort interface statt class ). Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Manchmal implementieren abstrakte Klassen keinerlei Code, sondern deklarieren nur nach außen sichtbare Methoden. Für solche Zwecke gibt es in Java ein spezielles Sprachelement, die so genannten Interfaces. Ein Interface wird in Java wie eine Klasse definiert (nur mit dem Schlüsselwort interface statt class ). Namen von Interfaces enden häufig auf -able. Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Programmieren gegen Interfaces Interfaces in Java dienen dazu, dem Programmierer die Möglichkeit zur Trennung von Schnittstelle und Implementierung zu geben. Interfaces Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Programmieren gegen Interfaces Interfaces in Java dienen dazu, dem Programmierer die Möglichkeit zur Trennung von Schnittstelle und Implementierung zu geben. Hierbei bietet es sich an, im Code dann Objektreferenzen vom Typ des Interfaces zu benutzen. Vorteile: Der Programmierer besitzt die Garantie, dass die referenzierten Objekte die im Interface deklarierten Methoden unterstüzten, Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Programmieren gegen Interfaces Interfaces in Java dienen dazu, dem Programmierer die Möglichkeit zur Trennung von Schnittstelle und Implementierung zu geben. Hierbei bietet es sich an, im Code dann Objektreferenzen vom Typ des Interfaces zu benutzen. Vorteile: Der Programmierer besitzt die Garantie, dass die referenzierten Objekte die im Interface deklarierten Methoden unterstüzten, aber die eigentliche Implementierung befindet sich in der Klasse, von der das referenzierte Objekt instanziert wurde, und bleibt so gekapselt. Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Beispiel: Bibliothek Bibliothek -inventar : Ausleihbar[] ... ... «interface» Ausleihbar +getAusleiher() : String +isAusgeliehen() : boolean +ausleihe(ausleiher : String) : void +rueckgabe() : void implements Ware -ausleiher : String +getAusleiher() : String +isAusgeliehen() : boolean +ausleihe(ausleiher : String) : void +rueckgabe() : void Buch -autor : String -titel : String ... +getAutor() : String +getTitel() : String ... DVD -regisseur : String -titel : String ... +getRegisseur() : String +getTitel() : String ... Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Unterschied: Abstrakte Klassen – Interface Methoden Attribute Vererbung Abstrakte Klassen Interfaces mindestens eine abstrakte Methode, aber zusätzlich nichtabstrakte erlaubt beliebig eine Klasse kann nur von einer einzigen abstrakten Klasse erben nur abstrakte Methoden erlaubt nur statisch eine Klasse darf beliebig viele Interfaces implementieren (und zusätzlich von einer Klasse erben) Polymorphie/Späte Bindung Abstrakte Klassen Interfaces Beispiel: Verwendung von Comparable p u b l i c c l a s s GewichtsWare e x t e n d s Ware implements Comparable ... } p u b l i c i n t compareTo ( Object a r g ) { i f ( a r g i n s t a n c e o f GewichtsWare ) { GewichtsWare o t h e r = ( GewichtsWare ) a r g ; i f ( gewicht < other . gewicht ) { return -1; } e l s e i f ( g e w i c h t == o t h e r . g e w i c h t ) { return 0; } e l s e return 1; } throw new I l l e g a l A r g u m e n t E x c e p t i o n ( " I l l e g a l Argument" }