Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Vererbung Helmut Paulus Speyer, 7./8.11.2006.

Ähnliche Präsentationen


Präsentation zum Thema: "Vererbung Helmut Paulus Speyer, 7./8.11.2006."—  Präsentation transkript:

1 Vererbung Helmut Paulus Speyer, 7./

2 Teil 1 Grafik mit Delphi

3 Zeichenfläche TCanvas
Canvas-Objekte dienen als Zeichenfläche für grafische Elemente. Sie kapseln eine Vielzahl von Methoden zur Ausgabe von Grafik und Text in einem rechteckigen Bereich. TCanvas-Werkzeuge Pen, Brush und Font, zuständig für bestimmte Teilaufgaben: TCanvas moveto(x,y : integer); lineto(x, y : integer); ellipse(x1,y1,x2,y2 : integer) rectangle(x1,y1,x2,y2 : integer) polygon(p : array of Tpoint); TextOut(x, y: Integer; const Text: string); ... Brush : TBrush Pen : TPen Font : TFont Pinsel – Füllfarbe, Muster ... Stift – Linienfarbe, Stil ... Schriftart – Farbe, Schrifttyp ... Der Koordinatenursprung (0,0) ist in der linken oberen Ecke einer Komponenten, die ein Canvas-Objekt zur Verfügung stellen.

4 Wie erhält man ein TCanvas-Objekt?
TCanvas-Objekte werden von einigen Delphi-Komponenten als Property zur Verfügung gestellt: z. B.: Formular, Paintbox, Image, Bitmap Der Koordinatenursprung ist die linke obere Ecke der jeweiligen Komponente. Die positive y-Achse zeigt nach unten. Die Image-Komponente speichert die Graphik zusätzlich in einer Hintergrundbitmap, so dass das Bild automatisch anzeigt wird, wenn das Formularfenster, nachdem es verdeckt war, wieder in den Vordergrund geholt wird. Das Formular und Paintbox zeichnen das Bild nur einmalig. Damit es nach dem Verdecken wieder erscheint, muss das Zeichnen der Graphik in der OnPaint-Ereignismethode der jeweiligen Komponente erfolgen. Dieses Ereignis wird vom Betriebssystem automatisch ausgelöst.

5 Objekthierarchie Das Bild-Objekt Bild vom Typ TImage verwaltet über das Attribut Canvas ein Leinwand-Objekt der Klasse TCanvas, das wiederum ein Zeichenstift-Objekt der Klasse TPen und ein Malpinsel-Objekt der Klasse TBrush verwaltet. Die entsprechenden Attribute Pen und Brush werden als Property zur Verfügung gestellt. Beispiel: Blaues Rechteck Bild.Canvas.Brush.Color := clbue; Bild.canvas.rectangle(10,10,100,20); Pinselfarbe blau Rechteck mit der linken oberen Ecke am Punkt (X1, Y1) und der rechten unteren Ecke am Punkt (X2, Y2).

6 Aufgaben 1 Testen Sie das Beispielprogramm Grafiktest
Variieren Sie verschiedene Modi der Pinsel und Stifte Testen Sie insbesondere den NotXOR-Füllmodus Das Programm soll wie folgt verbessert werden: Nach Wahl Kreise, Rechtecke oder Polygone zeichnen Position und Größe der Figur interaktiv durch Mausklicks bestimmen Kreis: Kreismittelpunkt und Radius Rechteck/Polygon: Eckpunkte

7 Zustandsbasierte Ablaufmodellierung
Eine Figur soll erzeugt werden: Ablauf: Figur auswählen Punkte bestimmen Figur zeichnen Zustände: Z0 Bereit Für Auswahl der Figur Z1 Figur gewählt für Punktaufnahme aktiviert Alter Zustand Auslösende Aktion Ausgelöste Aktion Neuer Zustand Z0 AuswahlBoxClick Punktefeld inizialisieren Z1 FormMausDown Punkt speichern [letzter Punkt] Figur zeichnen

8 Zustandsbasierte Ablaufmodellierung
Zustandsautomat: [nicht letzter Punkt] AuswahlBoxClick Punktearray inizialieren Z1: Figur gewählt Z0: Bereit [letzter Punkt] FormMouseDown Figur zeichnen Punkt aufnehmen Steuerung durch Ereignismethoden: AuswahlBoxClick : Figurtyp wählen FormMouseDown : Punkte speichern bis alle Punkte aufgenommen

9 Zustandsbasierte Modellierung
Zustandsbasierte Modellierung ist bei der Entwicklung von Systemen immer dann sinnvoll, wenn das Verhalten eines Systems nicht nur von äußeren Eingaben oder Ereignissen abhängt, sondern auch von inneren Zuständen, die das System in Abhängigkeit von den Eingaben bzw. Ereignissen durchläuft. Je nach Zustand kann ein Objekt anders auf dasselbe Ereignis reagieren. Ein Zustandsdiagramm ist immer genau einer Klasse zugeordnet. Es beschreibt das dynamische Verhalten der Objekte. In einem Zustandsdiagramm wird festgehalten: auf welche interne und externe Ereignisse ein Objekt reagiert, wie ein Objekt reagiert und welche Aktivitäten ausgelöst werden, wenn es sich in einem bestimmten Zustand befindet, in welchen Folgezustand ein Objekt übergeht als Reaktion auf ein Ereignis.

10 Implementierung Die gewählten Punkte werden gespeichert. Sind alle für die Figur notwendigen Punkte bestimmt, wird sie gezeichnet. type TZustand = (z0,z1); TGUI = class(TForm) procedure AuswahlBoxClick(Sender: TObject); procedure FormMouseDown(... X, Y: Integer); private { Private-Deklarationen} Zustand : TZustand; NMax : integer; Punkte : array of TPoint; procedure zeichneFigur; public { Public-Deklarationen} end; Typ der Zustandsvariablen mit den Konstanten z0, z1 Zustandsvariable Anzahl der Eckpunkte Dynamischer Array als Liste der Eckpunkte

11 Implementierung Figur auswählen im Zustand Z0
Punkte speichern im Zustand Z1 procedure TGUI.AuswahlBoxClick(...); begin if Zustand = z0 then case AusWahlBox.ItemIndex of 0,1 : NMax := 2; 2 : NMax := einlesen end; zustand := z1; Procedure TGUI.FormMouseDown(...,X,Y:Integer); Var nr : integer; begin if Zustand = z1 then begin // neuen Punkt dem Array hinzufügen nr := length(Punkte); //Punktzahl feststellen setLength(Punkte,nr+1); //Arraylänge erhöhen Punkte[nr] := Point(x,y); //Punkte zuweisen if nr = NMax-1 then // letzter Punkt? zeichneFigur; //Zustand z0 wiederherstellen Punkte := nil; //Punkte löschen Auswahlbox.ItemIndex := -1; Zustand := z0; end;

12 Teil 2 Projekt Minigolf

13 Minigolfanlage Ziel Start Ziel: Ball ins Loch schlagen

14 Modellierung der Animation
Idee: Benutzer klickt aufs Spielfeld Ball rollt schrittweise in Richtung der Verbindungslinie Maus – Ballmitte Bei jedem Schritt wird seine Geschwindigkeit geringer Spielende, wenn Zielpunkt erreicht Lösung: - Animationsschritte – timergesteuert (Ereignis: OnTimer) - Vermeidung von Flimmern durch Doppelte Pufferung Doppelte Pufferung – Double Buffering: Zusätzlich zum Bild auf dem Monitor wird noch ein Bild im Hintergrund gehalten. Hierzu wird ein zweites Canvas-Objekt für das Bild im Speicher benötigt. Alle graphischen Ausgaben erfolgen zunächst im Speicherbild; anschließend wird dieses auf dem Monitor ausgegeben.

15 OOA: Analyse Fachkonzept KStart KZiel Kreisobjekte Ball GUI-Schicht
Puffer Bitmap-Objekt Spielfeld Image-Komponente GUI Formular Steuerung Timer Animator

16 Beziehungen GUI-Schicht TForm TImage TGUI TBitmap TTimer TCanvas
ist ein 1 1 TImage TGUI TBitmap TTimer TCanvas Fachkonzept 2 benutzt 1 benutzt TKreis TBall

17 Modellierung der Klassen
TKreis xPos, yPos //Mittelpunkt FFarbe, FRad Canvas //Ref. auf Zeichenfläche create paint moveto // an neue Position TBall vx //Geschw. in x - Richtung vy //Geschw. in y – Richtung Zustand (liegt,rollt) ist ein rolle //verschieben um vx,vy setV getAbsV getZustand setZustand Objekte: instance of instance of KStart KZiel Ball

18 Implementierung der Klasse „TKreis“
xPos : integer yPos : integer FRad : integer - FFarbe : TColor - Canvas : TCanvas + Create(CanRef : TCanvas; x,y : integer) + paint + moveto(x,y : integer) + setAttribute(r : integer; f : TColor) constructor TKreis.create(CanRef : TCanvas; x,y : integer); begin xPos := x; yPos := y; canvas := CanRef;// Anbindung an GUI end; procedure TKreis.paint; var x1,y1,x2,y2 : integer; begin //umgebendes Rechteck x1 := xPos-Frad; y1 := yPos-Frad; x2 := xPos+Frad; y2 := yPos+Frad; with canvas do Pen.Mode := pmNotXor; Pen.Color := clblack; brush.color:= FFarbe; ellipse(x1,y1,x2,y2); end; Zeichnen im NotXOR-Modus ermöglicht Löschen der Figur nicht bei Doppelter Pufferung

19 Implementierung der Klasse „TKreis“
xPos : integer yPos : integer FRad : integer - FFarbe : TColor - Canvas : TCanvas + Create(CanRef : TCanvas; x,y : integer) + paint + moveto(x,y : integer) + setAttribute(r : integer; f : TColor) procedure TKreis.moveto(x,y : integer); begin //paint; //zum Löschen xPos := x; yPos := y; //paint;//erneut zeichnen end; procedure TKreis.setAttribute(r : integer;f : TColor); begin //paint; //zum Löschen FRad := r; FFarbe := f; end;;

20 Implementierung der Klasse „TBall“
Vererbung: Die Klasse TKreis wird erweitert; dabei werden die Attribute und Operationen an die abgeleitete Klasse weitergegeben. type TZustand = (liegt, rollt); TBall = class(TKreis) //abgeleitet von TKreis private vx,vy : double; Zustand : TZustand; public procedure rolle; procedure setV(x, y : double); function getAbsV : double; function getVx : double; function getVy : double; function getZustand : TZustand; procedure setZustand(z : TZustand); end; TKreis ist ein TBall vx : double vy : double; Zustand: TZustand + rolle; + setV(x, y : double); + getV : double; + getZustand : TZustand + getZustand

21 Implementierung der Klasse „TBall“
TKreis procedure TBall.rolle; begin if Zustand = rollt then xPos := round(xPos + vx); yPos := round(yPos + vy); setV(0.8*vx, 0.8*vy); end; ist ein TBall vx : double vy : double; Zustand : TZustand procedure TBall.setV(x, y : double); begin vx := x; vy := y; if getAbsV > 0.5 then Zustand := rollt else Zustand := liegt; end; function TBall.getAbsV : double; result := sqrt(vx*vx + vy*vy); + rolle; + setV(x, y : double); + getAbsV : double; + getZustand : TZustand + getZustand

22 Modellierung des Ballabschlags
Mausklick: Ball abschlagen Der liegende Ball, wird er durch Mausklick (x,y) abgeschlagen. Der Abschlag erfolgt in Richtung des Verbindungslinie Mauspunkt Ballmitte. vx V vy (x,y) Geschwindigkeitsvektor: vx = Ball.getx – x vy = Ball.gety – y Animation-OnTimer: Ball.rolle wird in der Ereignismethode der Timerkomponente ständig ausgerufen. Die Position wird neu berechnet und die Geschwindigkeit verringert. Eine Zustandsänderung (liegt) erfolgt, wenn sie zu klein wird.

23 Ball: Zustandsdiagramm
SpielFeldMouseDown setV(vx,vy) rollt liegt [|v|< 0,5] v [im Ziel] v [außerhalb] animiere rolle Rolle Zustände des Balls liegt v = 0 rollt |v| > 0,5 [|v| > 0,5] Alter Zustand Auslösende Aktion Ausgelöste Aktion Neuer Zustand liegt SpielfeldMouseDown Ball.setV(vx,vy) rollt BtnStartPosClick Startposition einnehmen Animiere Ball.rolle [Im Ziel] [außerhalb] Ball.rolle -> Bewegung [|v| > 0,5]/[|v| < 0,5] rollt/liegt

24 Modellierung des Spielablaufs
Spielphasen: Anforderungen: Sp0 Bahn vorbereitet Sp1 Bahn wird bespielt Sp2 Bahn beendet Sp3 Spiel beendet SpU unterbrochen Bei Spielbeginn Ball auf Startposition Kein Abschlag, wenn Ball im Loch oder außerhalb des Spielfeldes Bahn/Spiel zu Ende, wenn Ball im Loch Alter Zustand Auslösende Aktion Ausgelöste Aktionen Neuer Zustand Sp0 SpU BtnStartPosClick Ball auf Startpunkt Ball.setZustand(liegt) Punkte auf 0 Sp1 Strafpunkte SpielFeldMouseDown Ball.setV, Punkte erhöhen Animiere Ball.rolle [Eingelocht] [außerhalb] [im Locht&[alle Bahnen] Sp0 (Sp2) SpU (Sp3) Sp2 BtnNextBahn Bahn aufbauen/Ball auf Bahn

25 Zustandsdiagramm Spielablauf:
animiere SpielFeldMouseDown Ball.setV(vx,vy) SpU animiere [außerhalb] BtnStartPosClick Ball an Start BtnStartPosClick Ball an Start Strafpunkte Sp1 BtnNextBahn Bahn aufbauen Ball auf Bahn Sp2 Sp3 animiere [eingelocht & alle Bahnen] Sp0 animiere [eingelocht] In der einfachen Version (nur eine Spielbahn) entfallen die Zustände Sp2 und Sp3

26 Doppelte Pufferung Graphikausgabe in zwei Schritten: Spielfeld.canvas
Monitorbild Spielfeld : TImage Graphikausgabe in zwei Schritten: Spielfeld.canvas Zeichnen im Hintergrund: Puffer.canvas.ellipse(...); 2. Hintergrundbild ins Spielfeld kopieren: Spielfeld.canvas.draw(0,0,Puffer) Puffer.canvas Bei der Animation von bewegten Objekten wird das Hinter-grundbild vor jeder Änderung gelöscht, indem die Zeichen-fläche mit der Hintergrundfarbe gefüllt wird: Puffer.Canvas.fillRect(...); Hintergrundbild Puffer : TBitmap

27 Implementierung: Doppelte Pufferung
Idee: Alle Graphikausgaben erfolgen zunächst in ein Hintergrundbild, das dann als Ganzes in eine sichtbare Zeichenfläche kopiert wird. Einrichten des Puffers (OnCreate) var Puffer : TBitmap; //enthält das Hintergrundbild procedure TFenster.FormCreate( ... ); begin Puffer := TBitmap.Create; Puffer.Width := SpielFeld.Width; Puffer.Height := SpielFeld.Height; ... StartPkt := TKreis.create(Puffer.canvas,StartX,StartY); ZielPkt := TKreis.create(Puffer.canvas,400,100); Ball := TBall.create(Puffer.canvas,50,50); end; Bitmap-Objekt erzeugen Größe des Puffers anpassen Zeichenfläche des Puffers an Graphik-Objekte übergeben

28 Implementierung: Doppelte Pufferung
Hintergrundbild aufbauen und auf dem Monitor ausgeben procedure TFenster.zeichneSpielFeld; begin //altes Bild löschen (mit Hintergrundfarbe füllen) Puffer.Canvas.Brush.Color := SpielFeld.Canvas.Brush.Color; Puffer.Canvas.FillRect(rect(0,0,Puffer.width,Puffer.height)); //Graphische Objekte neu zeichnen im Hintergrund StartPkt.paint; ZielPkt.paint; Ball.paint; //Hintergrundbild in Zeichenfläche des Spielfeldes kopieren SpielFeld.Canvas.Draw(0,0,Puffer); end; Die Formular-Methode zeichneSpielfeld enthält alle Graphikbefehle. Sie wird nach jeder Aktualisierung eines Graphikobjekts aufgerufen. Benutzt man das Canvas-Objekt des Formulars als Monitorzeichenfläche, so kann das Zeichnen durch das OnPaint-Ereignis des Formulars ausgelöst werden.

29 Aufgaben 2 Programm Minigolf testen.
Programm so erweitern, dass Spielstände angezeigt werden. - pro Schlag ein Punkt - 2 Strafpunkte, wenn Ball von außerhalb zurückgeholt wird Reflexion an den Rändern des Spielfeldes Entwicklung eines magischen Feldes (Objekt), das den Ball vom Spielfeld schleudert, sobald er es betritt.

30 Modellierung grafischer Objekte
Teil 3 Modellierung grafischer Objekte

31 Anwendungsbeispiel Aktivitäten: verschieben, drehen, skalieren, editieren

32 Anforderungen Erzeugung und Verwaltung von grafischen Objekten unter-schiedlicher Form Fähigkeiten der Objekte frei verschiebbar (Maus) skalierbar drehbar

33 Erste OOA-Analyse Problem: Vielfalt der Objekte
TKreis TQuadrat TText TDreieck ... TRechteck TParallel Problem: Vielfalt der Objekte Optimierung: Entwicklung einer Klassenhierarchie

34 Klassenhierarchie TGrafikElement TKreis TPolygon TText TLinie TRegNEck
TRechteck TParallel

35 Klassenhierarchie 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.

36 Klassenhierarchie 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)

37 Einfaches Beispiel Kreise und Rechtecke

38 Kreise und Rechtecke TKreis xPos, yPos //Mittelpunkte FFarbe // Füllfarbe Canvas //Zeichenflächenref. Markiert // Markierungsflag FRad //Radius Create paint Moveto // verschieben skalieren //vergrößern TRechteck xPos, yPos //Mittelpunkte FFarbe // Füllfarbe Canvas //Zeichenflächenref. Markiert // Markierungsflag FBreite, 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!

39 Erste Modellierung der Klassen
Die Basisklasse enthält den gemeinsamen Kern aller grafischen Objektklassen. TGrafikElement xPos, yPos //Mittelpunkte FFarbe // Füllfarbe Canvas //Zeichenflächenref. Markiert // Markierungsflag Create //Basiskonstruktor Moveto // verschieben ist ein Basisklasse abgeleitete Klassen (Unterklasse) Generalisierung Spezialisierung TKreis FRad //Radius paint skalieren //vergrößern TRechteck FBreite, FLaenge

40 Implementierung der Basisklasse
TGrafikElement - xPos : integer - yPos : integer - FFarbe : TColor - Fmarkiert : boolean - Canvas : TCanvas + Create(CanRef : TCanvas; x, y : integer) + moveto(x, y : integer); + getX : integer + getY : integer TGrafikElement = class private xPos : integer; yPos : integer; FFarbe : TColor; Fmarkiert : boolean; Canvas : TCanvas; public constructor create(CanRef : TCanvas; x,y : integer); procedure moveto(x,y : integer); function getX : integer; function getY : integer; getFarbe Farbe : Tcolor; procedure setFarbe(wert : TColor); end;

41 Implementierung der Basisklasse
TGrafikElement - xPos : integer - yPos : integer - FFarbe : TColor - Fmarkiert : boolean - Canvas : TCanvas + Create(CanRef : TCanvas; x, y : integer) + getX : integer + getY : integer constructor TGrafikElement.create(CanRef : TCanvas; x,y : integer); begin xPos := x; yPos := y; canvas := CanRef; End; Die Objekte erhalten eine Referenz auf das Zeichenflächenobjekt des GUI-Objekts procedure TGrafikElement.moveto(x,y : integer); begin xPos := x; yPos := y; end;

42 „Ist ein“ - Beziehung TGrafikElement ... Die Unterklassen beschreiben nur die Abweichungen von von der Oberklasse. Alles andere kann wiederverwendet werden, weil es in der Oberklasse vorliegt. Die Methoden und Attribute der Oberklasse bilden eine Teilmenge der Methoden und Attribute der Unterklasse. Ein Objekt der Unterklasse hat somit ein Objekt der Oberklasse als Teilobjekt. Umgekehrt sind alle Objekte der Unterklasse eine Teilmenge der Objekte der Oberklasse. ist ein TKreis - FRad : integer - setRadius(wert : integer) + paint + setAttribute( r : integer, f : TColor) Jeder Kreis ist ein GrafikElement Konsequenz: Zuweisungskompatibilität Einer Variablen vom Typ der Oberklasse kann eine Referenz auf ein Unterklassenobjekt zugewiesen werden.

43 Implementierung der Klasse „TKreis“
TGrafikElement ... TKreis = class(TGrafikElement) private Frad : integer; public constructor create(CanRef : TCanvas; x,y : integer); procedure paint; procedure setAttribute(r : integer;f : TColor); function getRadius : integer; procedure setRadius(wert : integer); end; ist ein TKreis FRad : integer ... + paint + setAttribute( r : integer, f : TColor) + getRadius : ineger + setRadius(wert : integer)

44 Implementierung der Klasse „TKreis“
TGrafikElement ... constructor TKreis.create(CanRef : TCanvas; x,y : integer); begin inherited create(CanRef,x,y); //Konstruktor der Oberklasse FRad := 10; end; Durch Aufruf des geerbten Konstruktors werden die Attribute des Basisobjekts initialisiert. Das abgeleitete Objekt enthält quasi ein Basisobjekt als Teilobjekt. ist ein TKreis - FRad : integer - setRadius(wert : integer) + paint + setAttribute( r : integer, f : TColor)

45 Implementierung der Klasse „TKreis“
procedure TKreis.paint; var x1,y1,x2,y2 : integer; begin //umgebendes Rechteck x1 := xPos-Frad; y1 := yPos-Frad; x2 := xPos+Frad; y2 := yPos+Frad; with canvas do brush.color:= FFarbe; ellipse(x1,y1,x2,y2); end; TGrafikElement ... ist ein TKreis - FRad : integer + paint + setRadius(wert : integer) + setAttribute( r : integer, f : TColor) procedure TKreis.setAttribute(r : integer;f : TColor); begin FRad := r; FFarbe := f; end;

46 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.

47 Zuweisungskompatibilität
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 : TGrafikElement; Kreis := TKreis.create(...); Rechteck := TRechteck.create(..); ... Möglich: Grafik := Kreis; Grafik.setFarbe(clred); Grafik := Rechteck; Nicht möglich: Grafik.setAttribute(...) Grafik.setBreite(100); Beachte: Grafik ist eine Referenz auf den Teil des Kreisobjekts, der von TGrafikElement geerbt wird.

48 Operatoren „is“ und „as“
is - Operator : Typprüfung (Laufzeit) Beispiel: Var Figur : TGrafikElement; 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 des Objektes Kreis

49 Statische Methoden 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.

50 Statische Methoden Beispiel:
Zur Laufzeit werden verschiedene Grafikobjekte erzeugt und ihre Referenzen in einem Array als Container verwaltet: Var Figur : array[1..10] of GrafikElement; 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.

51 Virtuelle Methoden Lösung des Problems durch virtuelle Methoden:
TGrafikElement = class private ... public procedure paint;virtual; end; Die Basisklasse erhält ebenfalls eine Methode paint; diese wird aber als virtual deklariert. TKreis = class(TGrafikElement) private ... public procedure paint;override; end; paint wird in der Unterklasse überschrieben, d.h. als override deklariert und neu implementiert.

52 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 GrafikElement; 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.

53 Polymorphismus Merkmale Empfehlung
Das Konzept der dynamischen Bindung heißt in der OOP Polymorphismus (Vielgestaltigkeit). Merkmale Bei polymorphen Objektenvariablen entscheidet sich erst zur Laufzeit, welcher Klasse das Objekt angehört. Eine in einer Basisklasse als virtual deklarierte Methode definiert eine Schnittstelle für alle abgeleiteten Klassen, auch wenn diese noch nicht festgelegt sind. 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 Statische Methoden einer Basisklasse sollten nicht überschrieben werden. Wenn Überschreiben notwendig erscheint, sollte die Methode als virtual deklariert werden.

54 Abstrakte Klassen Die Basisklasse TGrafikElement 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. TGrafikElement = class ... procedure paint;virtual;abstract; end; TGrafikElement als abstrakte Klasse Merkmale: Abstrakte Klassen enthalten mindestens eine abstrakte virtuelle Methode, die überschrieben werden muss. Von abstrakten Klassen können keine Instanzen gebildet werden. Abstrakte Klasse bilden eine gemeinsame Schnittstelle für alle Unterklassen.

55 Aufgaben 3 Programm SimpelObjekt testen
Ergänzung der Objekte um die Funktion „Flaeche“. Der Zugriff soll polymorph erfolgen. Ableitung der Klasse TQuadrat von TRechteck und testen 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)

56 Teil 4 Objektverwaltung

57 Objektverwaltung Aufgaben eines Objektverwalters Realisierung
Referenzen unterschiedlicher Objekttypen speichern Einfügen, entfernen von Referenzen Zugriff auf einzelne Objekte oder alle ermöglichen Zeichnen aller Objekte Realisierung Speicher (lineare Liste) Array of TGrafikElement (dyn. Array) Lineare Liste entwickeln Vorhandene Container – Objekte nutzen oder anpassen (TList) Methoden Einfügen Entfernen Verschieben (innerhalb der Liste) Objekt an bestimmter Position ermitteln Zeichnen

58 Klassendiagramm TGUI TVerwalter - Elemente : TList *
SelObjekt : TGrafikElement Verwalter : TVerwalter FormCreate(...) FormPaint(...) FormMouseDown(...) FormMouseMove(...) TVerwalter - Elemente : TList + Count : integer + add(Objekt : TGrafikElement) + getElement( index : integer); + getElementAt(x, y : integer) : TGrafikElement + entferne(Objekt : TGrafikElement) + paintAll 1 * Der Verwalter hat ein Tlist-Objekt zur Aufnahme der Elemente TGrafikElement #F Markiert : boolean; #Farbe : Tcolor xPos : integer yPos : integer # zeichneMarke + paint getElementAt(x,y) - Element an der Position (x, y) der Zeichenfläche

59 Problem: Objekt auswählen
Objekt an der Stelle (x, y) Algorithmus: function TVerwalter.getElementAt(x, y : integer): TGrafikElement; var i, dx, dy : integer; Obj : TGrafikElement; begin result := nil; for i := 0 to Elemente.Count-1 do Obj := TGrafikElement(Elemente[i]); dx := x-Obj.getx; dy := y-Obj.gety; if dx*dx + dy*dy < 100 then result := Obj; end; Liste der Objekte durchlaufen und Abstand zum übergebenen Punkt (x,y) berechnen Abstandsbedingung prüfen Referenz des letzten gefundenen Objekts zurückgeben evtl. gefundenes Objekt ans Ende der Liste setzen, damit es als letztes gezeichnet wird und damit alle anderen überdeckt.

60 Zusammenfassung 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

61 Aufgaben 4 Erweiterung des Programms SimpelObjekt
Objektverwalter einbinden (Klasse TVerwalter (Unit: uVerwalter) 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

62 Realisierung des Tangram-Projekts
Teil 5 Realisierung des Tangram-Projekts

63 Anforderungen Erzeugung geometrischer Objekte Beschränkung auf Polygone und Kreise genügt Fähigkeiten der Objekte verschiebbar (Maus) skalierbar Drehbar Verwaltung der Objekte mit Hilfe eines Verwalter-Objekts

64 Darstellung eines Polygons
Canvas – Methode: procedure Polygon(Points array of TPoint) Der Parameter ist ein beliebig langes Array (dyn. Array) von Punkten (TPoint). Die Punkte enthalten die Bildschirmkoordinaten der Eckepunkte der Figur. Problem: - Der Referenzpunkt (xPos,yPos) soll Mittelpunkt der Figur sein. (erleichtert Drehen und Verschieben) - Die Figur soll um den Referenzpunkt gedreht werden. Lösung: Die aktuellen Bildschirmkoordinaten werden stets aus einem Basispolygon berechnet, dessen Mittelpunkt der Ursprung (0,0) ist. Alle Manipulationen (Vergrößerung, Verschiebung, Drehung) werden nur am Basispolygon durchgeführt und dieses anschließend zum Referenzpunkt verschoben.

65 Optimierte Klassen Reduzierung auf die Klassen TKreis und TPolygon
TGrafikElement TGrafikVerwalter + add(Element : TObjekt) + getElement( index : integer); + getElementAt(x, y : integer) : TGrafikElement # Markiert : boolean; ... 1 * # zeichneMarke + paint + moveto(x,y :integer) + skaliere(k : double) abstrakt TPolygon + initPolygon(... ); + paint + skaliere(k : double) + rotate(alpha : double) # SPunkte : Array of TPoint # BPunkte : array of TPunkt TKreis + paint;

66 Deklaration der Klasse „TPolygon“
TPolygon = class(TGrafikElement) protected Fn : integer; //Anzahl der Ecken SPunkte : array of TPoint; //aktuelle Bildschirmkoordinaten der Eckpunkte BPunkte : array of TPunkt; //Basispunkte (logische Koordinaten) procedure setSchwerpunkt(absolut : boolean); //Schwerpunkt als Mittelpunkt procedure zumRefPunkt; //Bildschirmkoordinaten der EckPunkte aktualisieren public procedure initPolygon(p : array of TPunkt; absolut : boolean);virtual; procedure paint;override; procedure moveto(x,y : integer);override; procedure skaliere(k : double);override; procedure rotate(alpha : double);virtual; function n : integer; end;

67 Klasse TPolygon Initialisierung:
+ initPolygon(... ); + paint + skaliere(k : double) + rotate(alpha : double) # SPunkte : array of TPoint # BPunkte : array of TPunkt Type TPoint = record x,y : integer end; TPunkt = record x,y : double end; Umwandlungsfunktionen function Point(x, y : Integer): TPoint; function Punkt(x, y : double) : TPunkt; Initialisierung: initPolygon(p : array of TPunkt; absolut : boolean) - übernimmt ein Punkte-Array und bildet daraus das Basispolygon. - absolut : gibt an, ob die Koordinaten absolute Bildschirmkoordinaten sind

68 Initialisieren des Basispolygons
Schritte: Initialisieren der dynamischen Arrays SPunkte und BPunkte Speichern der übergebenen Punkte in Bpunkte Polygon so verschieben dass der Ursprung zum Schwerpunkt wird Zum Referenzpunkt schieben, d. h. SPunkte bestimmen procedure TPolygon.setPolygon(p : array of TPunkt; absolut : boolean); //Basispolygon initialisieren var i : integer; begin Fn := Length(p); //Anzahl der Punkte ermitteln und speichern setLength(BPunkte,Fn); //dyn. Array mit Fn Werten initialisieren setLength(SPunkte,Fn); for i := 0 to Fn-1 do // Punkte in BPunkte speichern BPunkte[i] := p[i]; setSchwerpunkt(absolut); zumRefPunkt; // SPunkte aktualisieren end;

69 Schwerpunkt setzen procedure TPolygon.setSchwerpunkt(absolut : boolean); var i : integer; xs,ys : double; begin //Schwerpunkt des Basispolygons xs := 0; ys := 0; for i := 0 to Fn-1 do xs := xs + BPunkte[i].x; ys := ys + BPunkte[i].y; end; xs := xs/n; ys := ys/n; //Basispolygon so verschieben, dass der Schwerpunkt der Ursprung (0;0) wird for i := 0 to n-1 do BPunkte[i].x := BPunkte[i].x - xs; BPunkte[i].y := BPunkte[i].y - ys; if absolut then begin //Schwerpunkt wird Referenzpunkt xPos := round(xs); yPos := round(ys);

70 Verschieben des Basispolygons
Verschiebung des Basispolygons zum Referenzpunkt O BP1 BP0 BP3 BP2 P0 P3 P2 P1 M Procedure TPolygon.ZumRefPkt Für alle Punkte: P.x := xPos + BP.x; P.y := yPos + BP.y; BP : Basispunkte P : Bildschirmpunkte

71 Skalieren des Basispolygons
Zentrische Streckung des Basispolygons Procedure skaliere(k : double) BP0 BP1 BP2 BP3 BP0’ BP1’ BP2’ BP3’ Für alle Punkte: BP.x := k*BP.x; BP.y := k*BP.y; BP : Basispunkte k : Streckfaktor

72 Drehen des Basispolygons
Drehung eines Punktes um den Ursprung mit Drehwinkel a durch Multiplikation mit der Drehmatrix procedure TPolygon.rotate(alpha : double); Var i : integer; x,y : double; begin alpha := alpha*Pi180; for i := 0 to Fn-1 do x := cos(alpha)*BPunkte[i].x-sin(alpha)*BPunkte[i].y; y := sin(alpha)*BPunkte[i].x+cos(alpha)*BPunkte[i].y; BPunkte[i].x := x; BPunkte[i].y := y; end; zumRefPunkt;

73 Zeichnen des Polygons procedure TPolygon.paint; begin with canvas do
Pen.Style := pssolid; // Pen.Mode := pmNotXor; Pen.Color := clblack; brush.color := FFarbe; //Polygon zeichnen polygon(SPunkte); if Fmarkiert then zeichneMarke; //Markierungsrechteck end;

74 Anbindung an die GUI-Klasse
TForm Ereignisgesteuerter Ablauf: ist ein TGUI Figur : array[1..7] of TGrafikElement SelObjekt : TPolygon - Verwalter - ausgewähltes Objekt FormCreate(...) FormPaint(...) FormMouseDown(...) FormMouseMove(...) - Objekte erzeugen, Referenzen speichern - Objekte zeichnen - Objekt auswählen, drehen - Objekt verschieben

75 Aufgaben 5 In der Unit uGrafEleCont ist ein Graphikverwalter(Container) als Ableitung der Klasse TList implementiert. Binden Sie diesen Verwalter in das Tangram-Projekt ein. Leiten Sie die Klasse TLinie für eine Strecke zwischen zwei Punkten TPolygon ab und fügen Sie sie ins Projekt A5/GrafikObjTest ein.

76 Ausblicke Dialogfensters zum Editieren einzelner Objekte
Listenfenster zur Ansicht aller Objekte ...

77 Dialogfenster TForm TGrafEleDlg Initialisieren() Aktualisieren() Speichern() TGrafikElement Das Dialogfenster ist durch eine Referenz mit einem Objekt verbunden (initialisieren); es somit dessen Operationen aufrufen Aktualisieren liest die Attribute des Objekts und zeigt sie an Speichern schreibt die geänderten Attributwerte ins Objekt zurück

78 Implementierung Initialisieren des Dialogs
Var Grafik : TGrafikElement; procedure TGrafEleDlg.init(GrafObj : TGrafikElement); begin Grafik := GrafObj; aktualisiere; end; Öffnen des Dialogs im Formular SelObjekt := getElementAt(x,y); //angeklickte Figur finden if (SelObjekt <> nil) then begin //Dialog öffnen und initialisieren GrafEleDlg.init(SelObjekt);//Referenz übergeben GrafEleDlg.Show; end;

79 Aufgabe 6 Entwerfen Sie einen Editier- Dialog für das Projekt SimpelObjekt Binden Sie den Dialog ins Projekt ein

80 Literatur und Links Helmut Balzert: Lehrbuch der Software-Technik
Eckart Modrow: Informatik mit Delphi Band 1 / 2 Siegfried Spolwig: Klaus Merkert

81 Lösung: A 3.4 TKonto - FKontoNr : integer - FStand : double
Create (nr : integer) Auszahlen(Betrag : double) TSparkonto + Auszahlen(...) TGirokonto

82 Projekt Memory Zu entwickeln ist ein Programm, das das bekannte Memory-Spiel simuliert. Pflichten: /0/ In einer ersten Version spielt ein Spieler alleine. Durch Mausklick können die Spielkarten aufgedeckt werden. Der Computer ist dabei der Spielleiter. Der Punktestand des Spieler wird protokolliert /1/ In der zweiten Version ist der Computer ein Gegenspieler, der mit einer Gewinnstrategie ausgestattet ist. Prototyp:

83 Projekt Uhr

84 Ampelsteuerung Fußgängerübergang
Nach:

85 Ampelsteuerung Baustelle
Nach:


Herunterladen ppt "Vererbung Helmut Paulus Speyer, 7./8.11.2006."

Ähnliche Präsentationen


Google-Anzeigen