Vererbung Modellierung grafischer Objekte Helmut Paulus Speyer 5
Vererbung Modellierung grafischer Objekte Helmut Paulus Speyer, 5. -7. 11. 07
2 Anwendungsbeispiel Aktivitäten: verschieben, drehen, skalieren, editieren
3 Anforderungen • Erzeugung und Verwaltung von grafischen Objekten unterschiedlicher Form • Fähigkeiten der Objekte - frei verschiebbar (Maus) - skalierbar - drehbar
Erste OOA-Analyse 4 TKreis TQuadrat TText TDreieck . . . TRechteck TParallel Problem: Vielfalt der Objekte Optimierung: Entwicklung einer Klassenhierarchie
Klassenhierarchie 5 TGrafik. Element TKreis TReg. NEck TPolygon TLinie TParallel TRechteck TText
Klassenhierarchie 6 Optimierung der Klassen durch Entwicklung einer Vererbungsstruktur Ziele: • Der gemeinsame Kern aller Elemente wird in einer Basisklasse modelliert. • Spezialisierte Klassen werden von der Basisklasse abgeleitet; sie fügen spezielle Attribute und Operationen hinzu oder definieren bestimmte Dinge neu.
Klassenhierarchie 7 Vorteile: Durch Vererbung werden alle gemeinsamen Eigenschaften und Operationen an abgeleitete Klassen weitergegeben: Þ Grundlegende Attribute und Operationen werden nur einmal entwickelt Þ Möglichkeit zur Anpassung und Erweiterung unter geringem Aufwand (Wiederverwendbarkeit) Þ Einheitlicher Zugriff auf verschiedene Objekttypen wird möglich (Polymorphismus)
8 Einfaches Beispiel Kreise und Rechtecke
9 Kreise und Rechtecke TKreis TRechteck x. Pos, y. Pos //Mittelpunkte Farbe // Füllfarbe Canvas //Zeichenflächenref. markiert // Markierungsflag Rad //Radius Breite, FLaenge Create paint Moveto // verschieben skalieren //vergrößern Beide Klassen besitzen gleiche Attribute und Methoden gleicher Funktionalität. Das Gemeinsame muss nicht mehrmals implementiert werden!
10 Erste Modellierung der Klassen Die Basisklasse enthält den gemeinsamen Kern aller grafischen Objektklassen. Basisklasse Generalisierung TGrafik. Element x. Pos, y. Pos //Mittelpunkte Farbe // Füllfarbe Canvas //Zeichenflächenref. Markiert // Markierungsflag Create //Basiskonstruktor Moveto // verschieben ist ein abgeleitete Klassen (Unterklasse) TKreis ist ein TRechteck Rad //Radius Breite, Laenge paint skalieren //vergrößern Spezialisierung
11 Implementierung der Basisklasse TGrafik. Element - x. Pos : integer - y. Pos : integer TGrafik. Element = class private x. Pos : integer; - Farbe : TColor y. Pos : integer; - markiert : boolean Farbe : TColor; - Canvas : TCanvas markiert : boolean; + Create(Can. Ref : TCanvas; x, y : integer) + moveto(x, y : integer); + gib. X : integer + gib. Y : integer Canvas : TCanvas; public constructor create(Can. Ref : TCanvas; x, y : integer); procedure moveto(x, y : integer); function gib. X : integer; function gib. Y : integer; gib. Farbe : Tcolor; procedure setze. Farbe(wert : TColor); end;
12 Implementierung der Basisklasse TGrafik. Element - x. Pos : integer - y. Pos : integer - Farbe : TColor - markiert : boolean - Canvas : TCanvas + Create(Can. Ref : TCanvas; x, y : integer) + gib. X : integer + gib. Y : integer constructor TGrafik. Element. create(Can. Ref : TCanvas; x, y : integer); begin x. Pos : = x; y. Pos : = y; canvas : = Can. Ref; end; Die Objekte erhalten eine Referenz auf das Zeichenflächenobjekt des GUI-Objekts procedure TGrafik. Element. moveto(x, y : integer); begin x. Pos : = x; y. Pos : = y; end;
„Ist ein“ - Beziehung 13 TGrafik. Element . . . Die Unterklassen beschreiben nur die Abweichungen von der Oberklasse. Alles andere kann wiederverwendet werden, weil es in der Oberklasse vorliegt. Ein Objekt der Unterklasse hat somit ein Objekt der Oberklasse als Teilobjekt. ist ein TKreis - rad : integer Umgekehrt sind alle Objekte der Unterklasse eine Teilmenge der Objekte der Oberklasse. Jeder Kreis ist ein Grafik. Element - setze. Radius(wert : integer) Konsequenz: Zuweisungskompatibilität + paint + set. Attribute( r : integer, f : TColor) Einer Variablen vom Typ der Oberklasse kann eine Referenz auf ein Unterklassenobjekt zugewiesen werden.
14 Implementierung der Klasse „TKreis“ TGrafik. Element . . . TKreis = class(TGrafik. Element) private rad : integer; . . . public constructor create(Can. Ref : TCanvas; x, y : integer); procedure paint; ist ein procedure set. Attribute(r : integer; f : TColor); function gib. Radius : integer; TKreis -rad : integer -. . . + paint + set. Attribute( r : integer, f : TColor) + gib. Radius : ineger + setze. Radius(wert : integer) procedure setze. Radius(wert : integer); end;
15 Implementierung der Klasse „TKreis“ TGrafik. Element . . . constructor TKreis. create(Can. Ref : TCanvas; x, y : integer); begin inherited create(Can. Ref, x, y); //Konstruktor der Oberklasse . . . FRad : = 10; end; ist ein TKreis - rad : integer - setze. Radius(wert : integer) + paint + set. Attribute( r : integer, f : TColor) Durch Aufruf des geerbten Konstruktors werden die Attribute des Basisobjekts initialisiert. Das abgeleitete Objekt enthält quasi ein Basisobjekt als Teilobjekt.
16 Implementierung der Klasse „TKreis“ TGrafik. Element . . . ist ein TKreis - Rad : integer procedure TKreis. paint; var x 1, y 1, x 2, y 2 : integer; begin //umgebendes Rechteck x 1 : = x. Pos-Frad; y 1 : = y. Pos-Frad; x 2 : = x. Pos+Frad; y 2 : = y. Pos+Frad; with canvas do begin brush. color: = FFarbe; ellipse(x 1, y 1, x 2, y 2); end; + paint + set. Radius(wert : integer) + set. Attribute( r : integer, f : TColor) procedure TKreis. set. Attribute(r : integer; f : TColor); begin Rad : = r; Farbe : = f; end;
17 Vererbung und Zugriffrechte Elemente einer Klasse können in der Klassendeklaration vor dem Zugriff von außen geschützt werden (Geheimnisprinzip). Schutzebenen: public keine Zugriffsbeschränkung nach außen private Zugriff nur innerhalb einer Klasse protected Zugriff auch in abgeleiteten Klassen möglich Die Schutzebenen private und protected gelten allerdings nur für den Zugriff aus einer anderen Unit heraus. Vererbung der Zugriffsrechte Die Zugriffsrechte einer Klasse werden an abgeleitete Klassen vererbt. Schutzrechte können in einer abgeleiteten Klasse abgeschwächt, aber nicht verschärft werden.
Zuweisungskompatibilität 18 Konsequenz der „ist ein“ – Beziehung: Einer Objektvariablen einer Oberklasse können Objekte aller Unterklassen zugewiesen werden. Die Umkehrung gilt nicht. Beispiel: Var Kreis : TKreis; Rechteck : TRechteck Grafik : TGrafik. Element; . . . Kreis : = TKreis. create(. . . ); Rechteck : = TRechteck. create(. . ); . . . Möglich: Grafik : = Kreis; Grafik. setze. Farbe(clred); Grafik : = Rechteck; Nicht möglich: Grafik. setze. Attribute(. . . ) Grafik. setze. Breite(100); Hinweis: Grafik ist eine Referenz auf den Teil des Kreisobjekts, der von TGrafik. Element geerbt wird.
Operatoren „is“ und „as“ 19 is - Operator : Typprüfung (Laufzeit) Beispiel: Var Figur : TGrafik. Element; Kreis : TKreis; . . . if Figur is TKreis then TKreis(Figur). paint; Typumwandlung (type cast) - liefert true , wenn das Objekt Figur eine Instanz der angegebenen Klasse oder eines ihrer abgeleiteten Klassen ist as - Operator : Typumwandlung (Laufzeit) Beispiel: Kreis : = Figur as TKreis; (Figur as TKreis). paint; - liefert eine Referenz auf ein Objekt vom Typ Kreis
Statische Methoden 20 Die bisher definierten Methoden sind statisch: Beim Compilieren ist der Objekttyp bekannt, sodass die Sprungadresse der Methode festgelegt werden kann (statische Bindung) Kreis. paint; //paint - Methode des Kreisobjekts Rechteck. paint; //paint - Methode des Rechteckobjekts Der Typ der Referenz auf das Objekt bestimmt, welche Methode aufgerufen wird. Problem: Dieses Verhalten ist, wenn Vererbung ins Spiel kommt, oft unerwünscht. Z. B. wenn sich erst zur Laufzeit entscheidet, welcher Objekttyp angesprochen wird.
Statische Methoden 21 Beispiel: Zur Laufzeit werden verschiedene Grafikobjekte erzeugt und ihre Referenzen in einem Array als Container verwaltet: Var Figur : array[1. . 10] of Grafik. Element; Ziel: Einheitlicher Zugriff auf bestimmte Methoden, wie z. B. : for i : = 1 to 10 do Figur[i]. paint; Da zur Compilierzeit noch nicht feststeht, welche Objekttypen ins Array aufgenommen werden, entscheidet sich erst zur Laufzeit, welche Objektmethode aufgerufen werden soll. Dazu müsste der aktuelle Objekttyp für die Auswahl der Methode maßgebend sein.
Virtuelle Methoden 22 Lösung des Problems durch virtuelle Methoden: TGrafik. Element = class private. . . public. . . procedure paint; virtual; end; TKreis = class(TGrafik. Element) private. . . public procedure paint; override; . . . end; Die Basisklasse erhält ebenfalls eine Methode paint; diese wird aber als virtual deklariert. paint wird in der Unterklasse überschrieben, d. h. als override deklariert und neu implementiert.
23 Verhalten virtueller Methoden Die Referenz auf das Objekt enthält Information über den Typ des übergebenen Objekts. Dadurch kann die zum Objekt passende Methode aufgerufen werden. Var Figur : Array[1. . 10] of TGrafik. Element; Figur[5]. paint; //Aufruf der virtuellen Methode Der Typ des aktuellen Objekts bestimmt zur Laufzeit die Methode. Dynamische Bindung / late binding Interne Realisierung: Objekte besitzen einen Zeiger auf eine virtuelle Methodentabelle (VMT), die Zeiger auf alle virtuellen Methoden der Klasse enthält. Bei virtuellen Methoden erfolgt der Aufruf über diese Methodenzeiger-Tabelle.
Polymorphismus 24 Das Konzept der dynamischen Bindung heißt in der OOP Polymorphismus (Vielgestaltigkeit). Merkmale n Bei polymorphen Objektenvariablen entscheidet sich erst zur Laufzeit, welcher Klasse das Objekt angehört. n Eine in einer Basisklasse als virtual deklarierte Methode definiert eine Schnittstelle für alle abgeleiteten Klassen, auch wenn diese noch nicht festgelegt sind. n Ein Programm, das virtuelle Methoden einer Basisklasse enthält kann sehr leicht um abgeleitete Klassen erweitert werden, weil sichergestellt ist, dass stets die richtige Methode aufgerufen wird. Empfehlung n Statische Methoden einer Basisklasse sollten nicht überschrieben werden. n Wenn Überschreiben notwendig erscheint, sollte die Methode als virtual deklariert werden.
Abstrakte Klassen 25 Die Basisklasse TGrafik. Element muss die Methode paint enthalten, kann sie aber nicht sinnvoll implementieren, weil diese Klasse zu allgemein ist. Die Implementation kann also entfallen. Dazu wird die virtuelle Methode der Basisklasse zusätzlich als abstract deklariert. TGrafik. Element = class. . . procedure paint; virtual; abstract; . . . end; TGrafik. Element als abstrakte Klasse Merkmale: n Abstrakte Klassen enthalten mindestens eine abstrakte virtuelle Methode, die überschrieben werden muss. n Von abstrakten Klassen können keine Instanzen gebildet werden. n Abstrakte Klasse bilden eine gemeinsame Schnittstelle für alle Unterklassen.
Aufgaben 1 26 1. Entwickeln Sie ein Programm, das mehrere grafische Objekte anzeigt. 2. Verwenden Sie die Unit u. Graf. Ele. pas. 3. Ergänzen Sie die Objekte um die Funktion „gib. Flaeche“. Der Zugriff soll polymorph erfolgen. 4. Entwickeln Sie eine abstakten Oberklasse für alle Listen. 5. Polymorphismus anwenden: Eine Bank verfügt über Girokonten und Sparkonten. Während Girokonten überzogen werden können, dürfen Sparkonten keinen negativen Stand aufweisen. Der Auszahlungsaufruf soll für beide Kontotypen einheitlich sein Entwickeln Sie eine geeignete Vererbungsstruktur (UML)
27 Anhang Objektverwaltung
Objektverwaltung 28 Aufgaben eines Objektverwalters Referenzen unterschiedlicher Objekttypen speichern Einfügen, entfernen von Referenzen Zugriff auf einzelne Objekte oder alle ermöglichen Zeichnen aller Objekte Realisierung n Speicher (lineare Liste) n n Array of TGrafik. Element (dyn. Array) Lineare Liste entwickeln Vorhandene Container – Objekte nutzen oder anpassen (TList) Methoden n n Einfügen Entfernen Verschieben (innerhalb der Liste) Objekt an bestimmter Position ermitteln Zeichnen
Klassendiagramm 29 TVerwalter TGUI Sel. Objekt : TGrafik. Element Verwalter : TVerwalter 1 - Elemente : TList + Count : integer + add(Objekt : TGrafik. Element) Form. Create(. . . ) Form. Paint(. . . ) Form. Mouse. Down(. . . ) Form. Mouse. Move(. . . ) + get. Element( index : integer); + get. Element. At(x, y : integer) : TGrafik. Element + entferne(Objekt : TGrafik. Element) + paint. All * Der Verwalter hat ein Tlist. Objekt zur Aufnahme der Elemente get. Element. At(x, y) - Element an der Position (x, y) der Zeichenfläche TGrafik. Element #F Markiert : boolean; #Farbe : Tcolor x. Pos : integer y. Pos : integer # zeichne. Marke + paint
Problem: Objekt auswählen 30 Objekt an der Stelle (x, y) function TVerwalter. get. Element. At(x, y : integer): TGrafik. Element; var i, dx, dy : integer; Obj : TGrafik. Element; begin result : = nil; for i : = 0 to Elemente. Count-1 do begin Algorithmus: n Liste der Objekte durchlaufen und Abstand zum übergebenen Punkt (x, y) berechnen n Abstandsbedingung prüfen n Referenz des letzten gefundenen Objekts zurückgeben n evtl. gefundenes Objekt ans Ende Obj : = TGrafik. Element(Elemente[i]); der Liste setzen, damit es als dx : = x-Obj. getx; letztes gezeichnet wird und damit alle dy : = y-Obj. gety; anderen überdeckt. if dx*dx + dy*dy < 100 then result : = Obj; end;
Zusammenfassung 31 OOD- Klassendiagramm 1. Optimierung der Klassenstruktur Verwaltungs - Klassen hinzufügen Komplexe Klassen zerlegen 2. Optimierung der Attribute 3. Optimierung der Operationen 4. Optimierung der Vererbungsstruktur Abstrakte Operationen für einheitliche Schnittstellen Abstrakte Oberklassen bilden Polymorphismus maximieren Vererbungshierarchie komprimieren Existierende Klassen wiederverwenden
Aufgaben 4 32 Erweiterung des Programms Simpel. Objekt • Objektverwalter einbinden (Klasse TVerwalter (Unit: u. Verwalter) • Objekte mit der Maus über den Bildschirm ziehen • Farbe oder Größe einer mit Maus gewählten Figur ändern • Mit Hilfe der Maus beliebig viele Objekte interaktiv erzeugen
- Slides: 32