Vererbung Helmut Paulus Speyer, 7./8.11.2006.

Slides:



Advertisements
Ähnliche Präsentationen
Anzahl der ausgefüllten und eingesandten Fragebögen: 211
Advertisements

Objektorientierte Programmierung
Vorlesung: 1 Betriebliche Informationssysteme 2003 Prof. Dr. G. Hellberg Studiengang Informatik FHDW Vorlesung: Betriebliche Informationssysteme Teil3.
LS 2 / Informatik Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
LS 2 / Informatik Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
Kritische Betrachtung
Unter- und Oberklassen: Beispiel
Java: Objektorientierte Programmierung
Java2D Richard Göbel.
Sortierverfahren Richard Göbel.
Java: Dynamische Datentypen
Sortierverfahren Richard Göbel.
Java: Grundlagen der Objektorientierung
Polymorphie (Vielgestaltigkeit)
Rechneraufbau & Rechnerstrukturen, Folie 2.1 © W. Oberschelp, G. Vossen W. Oberschelp G. Vossen Kapitel 2.
Praktikum Entwicklung und Einsatz von Geosoftware I - Sitzung 5 Polymorphismus Sommersemester 2003 Lars Bernard.
Vorlesung: 1 Betriebliche Informationssysteme 2003 Prof. Dr. G. Hellberg Studiengang Informatik FHDW Vorlesung: Betriebliche Informationssysteme Teil2.
Java-Kurs - 7. Übung Besprechung der Hausaufgabe Referenzvariablen
Programmieren mit JAVA Teil V. Grafikausgabe mit JAVA, das AWT Java wurde von Anfang an mit dem Anspruch entwickelt, ein vielseitiges, aber einfach zu.
Vererbung Spezialisierung von Klassen in JAVA möglich durch
PKJ 2005/1 Stefan Dissmann Rückblick auf 2005 Was zuletzt in 2005 vorgestellt wurde: Klassen mit Attributen, Methoden und Konstruktoren Referenzen auf.
PKJ 2005/1 Stefan Dissmann Zusammenfassung Bisher im Kurs erarbeitete Konzepte(1): Umgang mit einfachen Datentypen Umgang mit Feldern Umgang mit Referenzen.
PKJ 2005/1 Stefan Dissmann Klassenhierarchie Person Kunde Goldkunde Lieferant Object.
Differentielles Paar UIN rds gm UIN
Prof. Dr. Bernhard Wasmayr
07-GraphischeObjekte Graphische Objekte in EMMA301Paint.
DVG Klassen und Objekte
Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
Prof. Dr. Bernhard Wasmayr VWL 2. Semester
Heute: Scherenzange zeichnen
1 Teil 4 Übung: Uhr. 2 Zielsetzung Ziel ist es, mit Hilfe objektorientierter Modellierung ein System zu entwickeln, mit dem eine einfache Uhr simuliert.
Rechneraufbau & Rechnerstrukturen, Folie 12.1 © W. Oberschelp, G. Vossen W. Oberschelp G. Vossen Kapitel 12.
Prof. Dr. Gerhard Schmidt pres. by H.-J. Steffens Software Engineering SS 2009Folie 1 Objektmodellierung Objekte und Klassen Ein Objekt ist ein Exemplar.
20:00.
Zusatzfolien zu B-Bäumen
Delphi II - OOP IFB Fortbildung
Grafikprogrammierung
Eine Einführung in die CD-ROM
Delphi TCanvas Informatik-AG. TCanvas Viele der sichtbaren in Delphi vorhanden Objekte besitzen die Eigenschaft Canvas. Übersetzt heißt Canvas Leinwand.
Syntaxanalyse Bottom-Up und LR(0)
Implementierung des Algorithmus von Dijkstra
Modellierung grafischer Objekte
Implementierung des Algorithmus von Dijkstra
Modellierung grafischer Objekte
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
OOP-Begriffe Abstraktion Modellieren Klasse Objekt Attribute Methoden
Ertragsteuern, 5. Auflage Christiana Djanani, Gernot Brähler, Christian Lösel, Andreas Krenzin © UVK Verlagsgesellschaft mbH, Konstanz und München 2012.
Geometrische Aufgaben
Zahlentheorie und Zahlenspiele Hartmut Menzer, Ingo Althöfer ISBN: © 2014 Oldenbourg Wissenschaftsverlag GmbH Abbildungsübersicht / List.
MINDREADER Ein magisch - interaktives Erlebnis mit ENZO PAOLO
1 (C)2006, Hermann Knoll, HTW Chur, FHO Quadratische Reste Definitionen: Quadratischer Rest Quadratwurzel Anwendungen.
Folie Beispiel für eine Einzelauswertung der Gemeindedaten (fiktive Daten)
Objektorientierte Modellierung mit UML
Programmiervorkurs WS 2014 Referenzdatentypen
Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen.
Folie Einzelauswertung der Gemeindedaten
Java-Kurs - 7. Übung Besprechung der Hausaufgabe Referenzvariablen
Datum:17. Dezember 2014 Thema:IFRS Update zum Jahresende – die Neuerungen im Überblick Referent:Eberhard Grötzner, EMA ® Anlass:12. Arbeitskreis Internationale.
OOP-Begriffe Abstraktion Modellieren Klasse Objekt Attribute Methoden
1 Medienpädagogischer Forschungsverbund Südwest KIM-Studie 2014 Landesanstalt für Kommunikation Baden-Württemberg (LFK) Landeszentrale für Medien und Kommunikation.
A Workshop About this chapter General description Units Time Schedule
Java-Kurs Übung Besprechung der Hausaufgabe Vererbung
Java-Kurs Übung Besprechung der Hausaufgabe
Java-Kurs Übung Besprechung der Hausaufgabe Vererbung
Einführung in die Programmierung mit Java
Tutorium Software-Engineering SS14 Florian Manghofer.
Dr. Wolfram Amme, Virtuelle Vererbung, Informatik II, FSU Jena, SS Auflösung von Konflikten bei Mehrfachvererbung Umbenennung mehrdeutiger Methoden.
1 Grundsätze objektorientierter Programmierung. Dr. Wolfram Amme, Grundsätze objektorientierter Programmierung, Informatik II, FSU Jena, SS Objektorientierte.
Java-Kurs Übung Klassen und Objekte: Vererbung (Fortsetzung)
 Präsentation transkript:

Vererbung Helmut Paulus Speyer, 7./8.11.2006

Teil 1 Grafik mit Delphi

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.

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.

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

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

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

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

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.

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

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;

Teil 2 Projekt Minigolf

Minigolfanlage Ziel Start Ziel: Ball ins Loch schlagen

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.

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

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

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

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

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;;

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

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

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.

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

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

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

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

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

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.

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.

Modellierung grafischer Objekte Teil 3 Modellierung grafischer Objekte

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

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

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

Klassenhierarchie TGrafikElement TKreis TPolygon TText TLinie TRegNEck TRechteck TParallel

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.

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)

Einfaches Beispiel Kreise und Rechtecke

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!

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

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;

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;

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

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)

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)

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;

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

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

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.

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.

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.

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.

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.

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.

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)

Teil 4 Objektverwaltung

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

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

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.

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

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

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

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

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.

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;

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;

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

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;

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);

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

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

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;

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;

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

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.

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

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

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;

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

Literatur und Links Helmut Balzert: Lehrbuch der Software-Technik Eckart Modrow: Informatik mit Delphi Band 1 / 2 Siegfried Spolwig: www.oszhdl.be.schule.de\gymnasium\faecher\informatik\index.htm Klaus Merkert http://hsg.region-kaiserslautern.de/faecher/inf/index.php

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

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:

Projekt Uhr

Ampelsteuerung Fußgängerübergang Nach: http://www.kbs.uni-hannover.de/Lehre/Info1/WS98/Projekte/atze/public_html/Presentation/

Ampelsteuerung Baustelle Nach: http://www.kbs.uni-hannover.de/Lehre/Info1/WS98/Projekte/atze/public_html/Presentation/