SWE-73 Objektorientierte Abstraktion Abstraktion auf der Ebene von Klassen (Beziehungen zwischen Klassen) • verbessert den Programmentwurf, • steigert die Wiederverwendbarkeit, • macht objektorientierte Bibliotheken einfach nutzbar. 1. Schnittstellenabstraktion (interfaces): eine Schnittstelle wird von mehreren Klassen implementiert und von anderen benutzt; z. B. eine Sortiermethode für Objekte aller Klassen, die eine Vergleichsmethode lessThan implementieren. © 1999 bei Prof. Dr. Uwe Kastens 2. Spezialisierung/Generalisierung (Vererbung, inheritance): speziellere Klassen zu allgemeineren Oberklassen zusammenfassen; z. B. Klasse Geometrics fasst Circles und Rectangles zusammen. 3. Wiederverwendung (Vererbung, inheritance): Aus gegebenen Klassen Unterklassen ableiten und bestimmte Methode ausfüllen; z. B. aus der Bibliotheksklasse Frame alle Methoden in eine Unterklasse übernehmen, nur die Methode paint individuell ausfüllen (siehe SWE-13, Olympische Ringe). Vorlesung Software-Entwicklung / Folie 73 Ziele: Vorschau auf mehrere Abstraktionsmethoden in der Vorlesung: Erläuterung der Beispiele nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.1 Übungsaufgaben: Schlagen Sie die 3 angesprochenen Beispiele nach. Verständnisfragen: Begründen Sie den Nutzen der Abstraktionen an den drei Beispielen. SWE-74 Schnittstellenabstraktion, Interfaces Objekte verschiedener Klassen werden einheitlich benutzt. Sicht auf Objekte ist durch das Interface begrenzt: nur spezifizierte Methoden sind benutzbar. © 2001 bei Prof. Dr. Uwe Kastens Interface spezifiziert Methoden Sortiermethode: Fernsteuerung Sortable [] arr arr[i].lessThan(..) Sortable lessThan Movable start, turn,… KlasseA KlasseB Circles Batch Plane Car Bike Methoden Methoden lessThan lessThan start turn ... start turn ... start turn ... Klassen implementieren die Methoden, die im Interface spezifiziert sind - und weitere Vorlesung Software-Entwicklung / Folie 74 Ziele: Prinzip der Schnittstellen verstehen in der Vorlesung: Erläuterung: Verallgemeinerung durch Einschränkung nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.1 Übungsaufgaben: Geben Sie weitere entsprechende Beispiele Verständnisfragen: SWE-75 Interfaces in Java Interface (Schnittstelle) in Java: Eine benannte Menge von Methodenspezifikationen ohne deren Implementierung: interface Movable { boolean start (); void stop (); boolean turn (int degrees); } Klassen können bestimmte Interfaces implementieren (auch mehrere): class Bike implements Movable { public boolean start () {...} // Implementierung von stop und turn sowie weiterer Methoden ... } class Car implements Movable, Motorized { // Implementierung der Methoden aus Movable und Motorized, sowie weiterer ... } Interfaces werden als Typabstraktion verwendet (Typ von Variablen): © 1999 bei Prof. Dr. Uwe Kastens Movable vehicle;... vehicle = new Bike();... vehicle.turn(20);... Typische Anwendung: Spezifikation von Eigenschaften (Movable), oder Rollen, damit Algorithmen möglichst allgemein formuliert werden können: void drive (Movable vehicle, Coordinate from, Coordinate to) { vehicle.start (); ... vehicle.turn (45); ... vehicle.stop (); } Vorlesung Software-Entwicklung / Folie 75 Ziele: Interfaces in Java kennenlernen in der Vorlesung: An typischen Anwendungen Interfaces erläutern nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.3 Übungsaufgaben: Suchen Sie Beispiele für Interfaces aus Java-Bibliotheken Verständnisfragen: Erläutern Sie, welche Methoden von den beiden Aufrufen vehicle.turn(...); ausgeführt werden. SWE-76 Beispiel: Interface für Sortierfunktionen Sortierfunktionen können unabhängig von dem Elementtyp formuliert werden. Voraussetzung: es gibt eine Ordnungsfunktion für den Elementtyp: interface Sortable { boolean lessThan (Sortable a); } © 1999 bei Prof. Dr. Uwe Kastens static void selectSort (Sortable [] arr) { // am Ende ist arr sortiert, so dass für kein i gilt: arr[i+1].lessThan(arr[i]) for (int left = 0; left < arr.length-1; left++) { // find smallest element from left to last int min = left; for (int j = left+1; j < arr.length; j++) if (arr[j].lessThan (arr[min])) min = j; // swap elements left and min: Sortable tmp = arr[min]; arr[min] = arr[left]; arr[left] = tmp; } } class Circles implements Sortable { public boolean lessThan (Sortable a) { return radius < ((Circles) a).getRadius(); } // unsicher implementiert ... } Circles [] cirarr; ... selectSort (cirarr); ... Vorlesung Software-Entwicklung / Folie 76 Ziele: Wirksamkeit der Schnittstellenabstraktion erkennen in der Vorlesung: Erläuterungen dazu nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.3 Übungsaufgaben: Wenden Sie die Sortierfunktion für Arrays verschiedener Klassen als Elementtypen an. Verständnisfragen: • Weshalb braucht man hier Wrapper-Klassen? • Warum ist das Cast-Konstrukt in der Methode lessThan unsicher? Wie kann man es sicher machen? SWE-76a Keller: Interface und Implementierung public interface Stack { void push (Object x); Object top (); } import java.util.Vector; void pop(); boolean isEmpty(); public class VectorStack implements Stack { private Vector elems; // Kellerelemente VectorStack () { elems = new Vector (); } public void push( Object x ) { elems.addElement (x); } // neues Element oben anfuegen © 1999 bei Prof. Dr. Uwe Kastens public void pop() // Falls Stack nicht leer oberstes Element entfernen { if (!elems.isEmpty()) elems.removeElementAt (elems.size()-1); } public Object top() // Falls Keller nicht leer oberstes Element { if (!elems.isEmpty()) // sonst kein Element zurückgeben return elems.lastElement (); else return null; } public boolean isEmpty() { return elems.isEmpty (); } } Vorlesung Software-Entwicklung / Folie 76a Ziele: Beispiel für ADT-Implementierungen abstrahiert durch Interface in der Vorlesung: • Erläuterungen dazu • Die Lösung der Aufgabe 23 zeigt eine weitere Implementierung des Kellers mit einer linaren Liste. nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.3 Übungsaufgaben: Verständnisfragen: SWE-77 Beispiel zur Implementierung eines Interface: Enumeration Schnittstelle zum Aufzählen der Elemente eines Behälter-Objektes, definiert in java.util: public interface Enumeration { boolean hasMoreElements(); Object nextElement();} Erweiterung der Klasse List, so dass sie Enumerations erzeugen kann: class List { ... // Eine innere Klasse implementiert Enumeration für List: class ListEnum implements Enumeration { Node current = start; // Objektvariable initialisiert mit dem Listenanfang public boolean hasMoreElements() { return current != null;} // Schnittstellenmethode public Object nextElement() // Schnittstellenmethode { if (current != null) { Object result = current.data; // Wert des Listenelementes current = current.link; // nächstes Paar return result; } else throw new NoSuchElementException("List Enumeration"); } } public Enumeration elements () { return new ListEnum ();} // Methode zur Erzeugung eines // "Enumeration"-Objektes } Vorlesung Software-Entwicklung / Folie 77 Ziele: Ein Interface implementieren lernen in der Vorlesung: Erläuterungen zu: • Enumeration als Interface • inneren Klassendeklarationen • Methoden des Interface nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.3 (Interface), 6.5 (Enumeration), 8.2 (Innere Klassen) nachlesen: /local/doc/java/docs/api/java.util.Enumeration.html Übungsaufgaben: Erzeugen Sie zu einem List-Objekt zwei Enumeration-Objekte und zeichnen sie alle beteiligten Objekte. Verständnisfragen: • Der Name der inneren Klasse ListEnum wird außerhalb der Klassendeklaration von List nicht verwendet. Aber Objekte der Klasse ListEnum werden außerhalb verwendet! Wie ist das möglich? SWE-77a Implementierung von Enumeration für den ADT List Interface und Klassen Objekte lotto Enumeration enum hasMoreElements nextElement Hashtable :ListEnum current List :List ListEnum HashEnum start prev now current start prev now Klassen mit inneren Klassen, die das Interface Enumeration implementieren List lotto = new List(); lotto.insert (new Integer (7)); ... Enumeration enum = lotto.elements(); while (enum.hasMoreElements()) {... enum.nextElement()...} 7 13 Vorlesung Software-Entwicklung / Folie 77a Ziele: Klassen und Objekte zu Folie 77 verstehen in der Vorlesung: Erläuterungen dazu nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.3 Übungsaufgaben: Verständnisfragen: 29 SWE-77b Zusammenfassung zur Schnittstellenabstraktion Typische Anwendungsfälle: 1. Abstraktion von Eigenschaften, charakterisiert durch die Schnittstellenoperationen; z. B. Interfaces Movable, Sortable, Motorized 2. Abstraktion von gleichartigen Operationen unterschiedlicher Klassen; z. B. Interface Enumeration: Elemente von Behälter-Objekten aufzählen 3. Abstraktion unterschiedlicher Implementierungen abstrakter Datentypen; z. B. Interface mit Kelleroperationen für verschiedene Implementierungen von Kellern Anwendungsmuster: Anwendung: Interface als Typ verwenden; Methoden des Interface auf Objekte anwenden Interface: nur notwendige Methoden spezifizieren Klassen: Methoden des Interface implementieren Vorlesung Software-Entwicklung / Folie 77b Ziele: Typischen Einsatz von Interfaces erkennen in der Vorlesung: Erläuterungen dazu und Beispiel der Keller-Implementierungen nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.3 Übungsaufgaben: Verständnisfragen: Die typischen Anwendungsfälle sind hier aus der Sicht des Entwurfs eines Interface dargestellt. Betrachten Sie nun eine einzige Klasse und geben Sie Beispiele für Interfaces unterschiedlicher Art, die die Klasse implementiert. SWE-77c Entwurfsmuster „Visitor“ Entwurfsmuster (Design Pattern): Beschreibung kooperierender Klassen und Objekte zur Lösung einer allgemeinen Entwurfsaufgabe, die immer wieder in unterschiedlichen Ausprägungen auftritt. Ziel: möglichst unabhängige, wiederverwendbare, wartbare Programmteile. Visitor ist eines von 23 Entwufsmustern in E. Gamma, et.al.: Design Patterns, Addison-Wesley, 1995 BinTree accept (TreeVisitor v) Datenstruktur mit Methode zum Durchlaufen: an jedem Knoten wird die visit-Methode eines nicht festgelegten Visitors aufgerufen { ... v.visit (this); ...} TreeVisitor void visit (BinTree b); Anwendungen: verschiedene Klassen mit Implementierungen der visit-Methode für unterschiedliche Aufgaben. this: das Objekt, auf das die Objektmethode gerade angewandt wird. TreeNodeCounter TreeNodeModifier visit (BinTree n) visit (BinTree n) {...count ...} {... modify...} Vorlesung Software-Entwicklung / Folie 77c Ziele: Ein Entwurfsmuster kennenlernen in der Vorlesung: • Erläuterung, des Prinzips • Bezug zu Aufgabe 27 • Bedeutung von this nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.3 nachlesen: E. Gamma, et.al.: Design Patterns, Elements of Reusable Object-oriented Software, Addison-Wesley, 1995 Übungsaufgaben: Aufgabe 27 auf Blatt 9 Verständnisfragen: • Vergleichen Sie den Visitor mit dem Enumeration Interface, mit dem auch Datenstrukturen durchlaufen werden. SWE-78 Vererbung Vererbung (Inheritance): hierarchische Relation zwischen Klassen zur Spezialisierung: Objekte einer Unterklasse können wie Objekte der Oberklasse behandelt werden. Wiederverwendung: Unterklasse erbt die Implementierung der Oberklasse Oberklasse allgemeiner spezieller Unterklasse Beispiele: Geometrics Tiere Diesel Circles Lebewesen Motor Elektro Benziner Rectangles Pflanzenfresser Elephanten Nashörner Pflanzen ... ... Bäume ... Eichen Einfache Vererbung (Java): Vererbungsrelation ist ein Baum. Die Klasse Object ist in Java implizit die Wurzel jedes Vererbungsbaumes. Bildung von Objekten ist meist nur für Klassen an den Blättern sinnvoll - Oberklassen sind Abstraktionen. Vorlesung Software-Entwicklung / Folie 78 Ziele: Spezialisierungshierarchien kennenlernen in der Vorlesung: • Spezialisierung erläutern • Kontrast der Beziehungen: ist-ein und hat-ein • häufiger Entwurfsfehler nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.2) Übungsaufgaben: Weitere Beispiele für Spezialisierungen angeben Verständnisfragen: Warum sind bei diesen Hierarchien nur Objekte von Blattklassen sinnvolle Modellierungen? SWE-79 Beispiel für Vererbung abstract class Geometrics { int getX () { return x; } int getY () { return y; } void move (int dx, int dy) { x += dx; y += dy; } Geometrics (int ix, int iy) { x = ix; y = iy; } class Circles extends Geometrics { double getRadius () { return radius; } void grow (double dr) { radius += dr; } Circles (int ix, int iy, double ir) { super (ix, iy); radius = ir; } private int x,y; } private double radius; } :Circles x y radius class Rectangles extends Geometrics { Rectangles (int ix, int iy, double l, double w) { super (ix, iy); length = l; width = w; } ... } • Oberklasse Geometrics ist als abstract gekennzeichnet: keine Objekte dieser Klasse • Circles und Rectangles erben die x-, y-Koordinaten und die Methoden darauf • Circles und Rectangles definieren weitere, speziellere Methoden und Objektvariable Vorlesung Software-Entwicklung / Folie 79 Ziele: Nutzen der Vererbung erkennen in der Vorlesung: • Inhalt von Objekten • super-Konstruktor nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.2 Übungsaufgaben: • Vervollständigen Sie die Implementierung • Suchen Sie Beispiele für Spezialisierungshierarchien aus einer Java-Klassenbibliothek Verständnisfragen: Erläutern Sie die Bedeutung der Koordinaten der Oberklasse in bezug auf jede der Unterklassen. SWE-80 Polymorphie: Variablentypen Polymorphie (Vielgestaltigkeit): Objekte verschiedener Unterklassen können wie ein Objekt der gemeinsamen Oberklasse behandelt werden. D. h. allgemeinere Methoden der Oberklasse können auf speziellere Objekte von Unterklassen angewandt werden. Beispiele für Ober- und Unterklassen als Variablentypen: Circles cir = new Circles (1, 2, 3.0); Rectangles rec = new Rectangles (3, 4, 5.0, 6.0); Geometrics geo; Variable abstrahiert von der Art der Figur geo = cir; geo.move (1, 1); geo = rec; geo.move (2, 3); rec = (Rectangles)geo; rec = geo; Typausweitung: Circles -> Geometrics Aufruf einer allgemeinen Methode wie oben einengendes Type cast: Geometrics -> Rectangles kann ClassCastException auslösen Fehler bei der Übersetzung Gleiches gilt für Interfaces und Klassen, die sie implementieren: Movable vehicle = new Car(); Car meinAuto = (Car)vehicle; Vorlesung Software-Entwicklung / Folie 80 Ziele: Oberklassen als allgemeinere Typen verstehen in der Vorlesung: Polymorphie, Typregeln und Beispiele erläutern nachlesen: Übungsaufgaben: Verständnisfragen: Erläutern Sie die Anpassungen der Objektreferenzen. SWE-81 Polymorphie: dynamische Methodenbindung Dynamische Methodenbindung (Prinzip von OO-Sprachen, neben Klassen und Vererbung): Welche Methode aufgerufen wird bestimmt die Klassenzugehörigkeit des Objektes zur Laufzeit - nicht der Typ der Variablen, die die Objektreferenz enthält. • Dynamische Methodenbindung bei Interface-Typen: Movable vehicle = ...; vehicle.start(); • Dynamische Methodenbindung durch überschreiben: In einer Unterklasse können Methoden definiert werden, die mit gleichem Namen, gleichen Typen von Parametern und Ergebnis auch in einer Oberklasse definiert sind. Sie überschreiben die der Oberklasse. Sie sollten konzeptuell das gleiche leisten, nur spezieller. abstract class Motor { void on () {...} void off () {...} void accelerate (...) {...} ... } class Diesel extends Motor { void glueh () {...} void on () // überschreibt { glueh(); super.on(); } ... } class Elektro extends Motor ... Ein Aufruf m.on() führt je nach Inhalt von m auf die Motor-, Diesel- oder Elektro-Methode. • Dynamische Methodenbindung bei abstrakten Methoden (siehe SWE-82): In der Klasse Motor kann man die Implementierung der Methode on durch eine Spezifikation der Methode on ersetzen. (Es gibt keine allgemeinen Motor-Objekte.) Vorlesung Software-Entwicklung / Folie 81 Ziele: Die Konzepte "Überschreiben" und "dynamisches Binden" von Methoden verstehen in der Vorlesung: • Erläuterungen am Beispiel • Vergleich zu einer Fallunterscheidung über Unterklassen nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.2 Übungsaufgaben: Implementieren Sie die Beispiele und überzeugen sich von der Wirkung der dynamischen Bindung. Verständnisfragen: SWE-82 Abstrakte Methoden und Klassen Abstrakte Methode: Spezifikation einer Methode ohne ihre Implementierung; d. h. nur Name, Ergebnistyp und Parametertypen (Signatur der Methode, wie in Interfaces). Sie muß in jeder Unterklasse implementiert werden. Abstrakte Klasse: Eine Klasse, zu der man keine Objekte bilden kann - nur zu ihren Unterklassen. Nur solche Klassen dürfen abstrakte Methoden haben. Zweck: Eine allgemeine Aufgabe (z. B. Fläche berechnen) wird in der Oberklasse spezifiziert und in den Unterklassen unterschiedlich implementiert: abstract class Geometrics { ... abstract double area (); ... } class Circles extends Geometrics { ... double area () { return Math.PI*radius*radius; } ... } g.area() kann für eine Variable g vom Typ Geometrics aufgerufen werden; dynamische Methodenbindung findet die zum Objekt passende Implementierung. Abstrakte Klassen liegen in der Vererbungshierarchie (Interfaces liegen daneben). Abstrakte Klassen können auch implementierte Methoden und Objektvariable haben (anders als Interfaces). Vorlesung Software-Entwicklung / Folie 82 Ziele: Abstrakte Methoden in Oberklassen kennenlernen in der Vorlesung: • Bezug zum Überschreiben von Methoden • Gegenüberstellung zu Interfaces nachlesen: 9.4 Übungsaufgaben: Verständnisfragen: • Welche der Klassen auf Folie 78 wird man wohl als abstrakte Klassen realisieren? SWE-82a Zusammenfassung zur Vererbung • Die Unterklasse B erbt Methoden und Variable von der Oberklasse A; d. h. die Methoden und Variable von A sind auch für B definiert. Oberklasse class A • Ein B-Objekt kann wie ein A-Objekt behandelt werden: - zu einem B-Objekt Methoden aufrufen, die in A definiert sind - Referenz des B-Objektes an eine Variable vom Typ A zuweisen. • Ein B-Objekt enthält auch Objektvariable, class B extends A Unterklasse die in A definiert sind. • Ein B-Objekt bleibt immer ein B-Objekt, auch wenn seine Referenz an Variable anderen Typs zugewiesen wird. • In den Methodendefinitionen von B können Methoden von A aufgerufen und Variable von A benutzt werden, sofern sie nicht private sind. Vorlesung Software-Entwicklung / Folie 82a Ziele: Regeln zur Vererbung in der Zusammenfassung in der Vorlesung: Erläuterungen dazu am Beispiel von SWE-79 nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.2 Übungsaufgaben: Verständnisfragen: SWE-82b Vererbung und verwandte Konzepte Sei A eine Oberklasse von B und in A sei eine Methode m implementiert, z. B. class A { int m (String s) {...} ...} class B extends A {...} 1. Wenn in B m nicht definiert ist, erbt B die Methode m. 2. Wenn in B eine Methode m mit gleichen Parametertypen definiert ist, überschreibt sie das m aus A. Der Ergebnistyp muss dann auch gleich sein. 3. Wenn in B eine Methode m definiert ist, deren Parametertypen sich von denen von m in A unterscheiden, dann sind die beiden Methoden in B überladen. Ebenso, wenn in A eine weitere Methode m mit anderen Parametertypen definiert wird. 4. Wenn B Klassenmethode (static) m definiert, deren Parametertypen mit denen von m in A übereinstimmt, dann verdeckt m in B die Methode m in A, d. h. m aus A ist in B nicht sichtbar. m in A muss dann auch static sein. Sei A eine Oberklasse von B und in A sei eine Methode m spezifiziert, z. B. abstract class A { abstract int m (String s); ...} class B extends A {...} 5. Wenn B nicht abstract ist, muss in B m mit denselben Parameter- und Ergebnistypen implementiert werden. Vorlesung Software-Entwicklung / Folie 82b Ziele: Unterschiede der Konzepte verstehen in der Vorlesung: Zu jedem der 5 Konzepte wird ein Beispiel graphisch mit Ober- und Unterklasse gezeigt und erläutert. nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.2 Übungsaufgaben: Verständnisfragen: SWE-83 Wiederverwendung von Klassen aus Bibliotheken Die Klasse java.awt.Frame implementiert gerahmte Fenster in graphischen Benutzungsoberflächen (GUI). Sie ist eine Blattklasse in der Hierarchie der GUI-Komponenten: java.lang.Object java.awt.Component java.awt.Container java.awt.Window java.awt.Frame GUI-Komponenten solche, die wieder Komponenten enthalten können Fenster ohne Rahmen Fenster mit Rahmen Methoden zum Zeichnen, Plazieren, Bedien-Ereignisse Behandeln, etc. sind auf den jeweils passenden Hierarchieebenen implementiert. In der abstract class Component ist die Methode public void paint (Graphics g) definiert, aber nicht ausgefüllt. Mit ihr wird auf der Fläche des Fensters gezeichnet. Benutzer definieren Unterklassen von Frame. Sie erben die Funktionalität der Oberklassen. Die Methode paint wird überschrieben mit einer Methode, die das Gewünschte zeichnet: class Rings extends Frame { public Rings () { setTitle ("Olympic Rings"); } public void paint (Graphics g) { // draw olympic rings ... } public static void main (String [] args) { Frame f = new Rings(); ... } } Vorlesung Software-Entwicklung / Folie 83 Ziele: Einsatz von OO-Techniken zur Wiederverwendung in der Vorlesung: Einen Eindruck von Umfang und Komplexität der geerbten Methoden vermitteln nachlesen: Judy Bishop: Java lernen, 3.Aufl., Abschnitt 9.2, 9.4 Übungsaufgaben: • Schlagen Sie die Klasse Frame in der Java-Dokumentation nach. • Schlagen Sie das Programm "Olympic Rings" auf Folie 13 und im Buch nach. Verständnisfragen: