Grundkonzepte der objektorientierten Programmierung mit Delphi Helmut Paulus
Grundkonzepte der objektorientierten Programmierung mit Delphi Helmut Paulus Speyer, 13. 05. 09
Problem der Softwareentwicklung 2 Die Größe und Komplexität der Programme nimmt zu n Die Pflege immer aufwändiger n Ab einer bestimmten Größe versteht niemand mehr das Programm n Das Programm kann nicht mehr geändert werden Derzeitige Lösung des Problems: § Objektorientierte Programmierung § Entwurfsmuster für graphische Benutzungsoberflächen v u. a. MVC: Modell-Ansicht-Steuerung
Objekte und Klassen 3 Statt eines riesigen Programm hat man Objekte n n Programmbausteine, die bestimmte Aufgaben eigenständig lösen Objekte kooperieren miteinander bei der Lösung eines komplexen Problems Klassen n Baupläne für Objekte n Jedes Objekt gehört zu genau einer Klasse n Objekte mit gemeinsamen Eigenschaften bilden ein Klasse
MVC-Entwurfsmuster 4 Model/View/Controller Grundlegendes Konzept zum Aufbau von Benutzerschnittstellen Model: das Anwendungsobjekt View: Bildschirmdarstellung des Anwendungsobjekts Controller: nimmt Benutzereingaben entgegen und modifiziert das Anwendungsobjekt 60 views 40 20 0 a Tastatureingaben controller b c a = 30% b = 50% c = 20% model Kennzeichen: Trennung von Benutzungsoberfläche (GUI) und Fachkonzept (Model)
MVC-Uhr 5 Aufgabe: Eine einfache Uhr mit digitaler Anzeige soll mit Hilfe von geeigneten Objekten realisiert werden. 12 : 14 : 04 Anforderungen: 1. 2. Die Uhr soll dabei vorerst noch nicht selbst laufen. Die Uhr soll als eigenständiger Baustein, der unabhängig von GUI-Objekten ist, entwickelt werden. Modell Uhr Darstellung schreibt liest GUI Steuerung Std= 12 Min= 17 Sec = 0 Fachkonzept
MVC-Architektur 6 View liest Ansicht Informiert ? Model (Daten, Verarbeitung) schreibt Controller Steuerung Fachkonzept GUI (Graphical User Interface) § View und Controller bilden zusammen die Benutzungsoberfläche (GUI).
Trennung von GUI und Datenmodell 7 Das bedeutet: § Das Modell kennt weder View noch Controller. In den Datenklassen werden keine View– oder Controllermethoden aufgerufen! § View und Controller kennen das Modell und lesen und schreiben die Daten. § Zwischen den GUI-Objekten und den MODELL-Objekten werden Verbindungen hergestellt, um einen Datenaustausch zu ermöglichen. Vorteile: n Änderungen der Benutzeroberfläche haben daher keine Auswirkung auf die interne Verarbeitung der Daten und der Datenstruktur. n n n Verbesserung der Wiederverwendbarkeit klare Strukturierung eines Programms Die Daten können gleichzeitig mehrfach auf unterschiedliche Weise dargestellt werden.
Fragen und Probleme 8 n Wie erreicht man die Entkopplung? n Wie greifen View und Controller auf die Daten zu? n Wie können die Views aktualisiert werden, wenn das Modell keinen Zugriff auf sie hat? n Wie erfahren die Views, dass sich die Daten des Modells geändert haben?
Realisierung in Delphi 9 Entkopplung: • GUI- und Modellklassen in verschiedenen Units halten • View und Controller in einem Formular (z. B. u. GUI. pas) unterbringen • Modell-Klasse in einer eigenen Unit (z. B. u. Modell. pas) speichern Datenzugriff: • Die GUI-Klasse erhält eine Referenz auf das Modell-Objekt. • Der Datenzugriff erfolgt mit Lese- und Schreibmethoden, des Modells (z. B. set. Attribut() bzw. get. Attribut()). Aktualisierungsmöglichkeiten: • Die Views fragen (evtl. permanent) das Modell ab (Polling). • Die Views werden durch Ereignisse des Modells über Datenänderungen informiert und aktualisieren sich daraufhin. (Selbstdefinierte Ereignisse) • Benachrichtigung mittels Beobachter-Muster (Observer-Pattern)
Modellierung der Uhr 10 OO-Analyse Überlegungen zur Objektstruktur • Welche Merkmale sind charakteristisch für eine Uhr, also allen Uhrentypen gemeinsam? • Welche Funktionalitäten gehören zu den Basiseigenschaften einer Uhr? Bzw. Welche Dienste muss eine Uhr zur Verfügung stellen, um ihre Aufgabe zu erfüllen? • Lässt sich das Objekt Uhr noch zerlegen? Identifikation von Objekten: Ø Zähler für Sekunden und Minuten (modulo 60), Zähler für Stunden (modulo 24) Ø Idee: Die Klasse TUhr soll Zählerobjekte modulo einer vorgebbaren Grenze nutzen können Ergebnisse der Analyse: Attribute: Zählerstand – Werte von 0 bis Maximalwert Fähigkeiten: - zählt weiter bis ein maximaler Wert erreicht ist, dann wieder bei Null - zurücksetzen in den Startzustand (Zählerstand 0) - einen bestimmten (Anfangs-)Zählerstand setzen
Modellierung der Klasse TUhr 11 OO-Analyse • • Die Uhr besitzt drei Zählerobjekte als Stunden-, Minuten- und Sekundenzähler. Stunden, Minuten und Sekunden können gesetzt werden. Stunden, Minuten und Sekunden können ausgelesen werden. Die Uhrzeit kann schrittweise erhöht werden. Kurzbeschreibung: • • • Das Uhrobjekt verwaltet die Zählerobjekte, d. h. es erzeugt und vernichtet sie. Gemäß dem Geheimnisprinzip werden die Zählerobjekte als private bzw. protected deklariert, sind also dem Benutzer verborgen. Der Zugriff erfolgt indirekt mit Hilfe der Set- und Get-Methoden. OOA-Klassendiagramm
TModulo. Zaehler 12 TModulo. Zaehler = class private max: integer; stand: integer; public constructor create(m: integer); procedure set. Stand(s: integer); procedure null. Setzen; procedure weiter. Zaehlen; function get. Stand: integer; end; constructor TModulo. Zaehler. create(m: integer); begin max : = m; stand : = 0; end;
TUhr 13 TUhr = class protected min : TModulo. Zaehler; Uhr verwaltet 3 Zählerobjekte sec : TModulo. Zaehler; (hat-Beziehung) std : TModulo. Zaehler; public //Methoden constructor create; destructor destroy; override; procedure ticke; procedure reset; …. end; constructor TUhr. create; begin std : = TModulo. Zaehler. create(23); min : = TModulo. Zaehler. create(59); sec : = TModulo. Zaehler. create(59); end; Erzeugung der Zählerobjekte
14 TUhr destructor TUhr. destroy; begin std. Free; Vernichtung der Zählerobjekte min. Free; sec. Free; inherited destroy; //geerbten Destruktor aufrufen end; procedure TUhr. ticke; begin Die Uhr tickt. sec. weiter. Zaehlen; if sec. get. Stand = 0 then begin min. weiter. Zaehlen; if min. get. Stand = 0 then std. weiterzaehlen; end; Aktivieren der Zähler
Entwicklung der GUI 15 OO-Entwurf Prototyp OOD-Klassendiagramm
Objektverwaltung 16 Das Formular verwaltet die GUI-Objekte und das Modellobjekt. uses … m. TUhr; Modell-Unit einbinden TGUI = class(TForm) … private { Private-Deklarationen } Uhr : TUhr; //Referenzvariable Uhr (als Attribut des Formulars) procedure zeit. Anzeigen; //View-Methode des Formulars public Zeiger auf ein Uhrobjekt hat Beziehung { Public-Deklarationen } end; procedure TGUI. Form. Create(Sender: TObject); begin Uhr : = TUhr. create; //Uhrobjekt erzeugen zeit. Anzeigen; end; Uhrobjekt erzeugen
Controller / View 17 procedure TGUI. BSetzen. Click(Sender: TObject); Ereignisprozedur var h, min : integer; begin h : = Str. To. Int(Ed. H. text); min : =Str. To. Int(Ed. Min. text); Uhr. Set. Min(min); Datenfluss: Controller Modell Uhr. Set. Std(h); zeit. Anzeigen; end; procedure TGUI. zeit. Anzeigen; var h, min, sec : integer; Aktualisierung der Anzeige (Polling) sh, smin, ssec : string; begin h : = Uhr. Get. H; min : = Uhr. Get. Min; sec : = Uhr. get. Sec; sh : = Intto. Str(h); min: = Intto. Str(min); ssec: = Intto. Str(sec); if h < 10 then sh : = '0'+sh; …. . PZeit. Anzeige. Caption : = sh+': '+smin+': '+ssec; end; Datenfluss: Modell View
18 Aufgaben 1. Testen Sie das Programm ‚Uhr 0’ und verfolgen Sie den Ablauf mit Hilfe des Einzelschritt-Modus (Debugging). 2. Implementieren Sie einen Timer zur automatischen Weiterschaltung der Uhr. 3. Erzeugen Sie im Formular eine zweite Uhr. 4. Ersetzen Sie die Digitalanzeige durch ein Analoganzeige (TZiffernblatt) 5. Implementieren Sie ein selbstdefiniertes Ereignis, sodass die Uhr die GUI bei Zustandsänderung informieren kann. 6. Die Uhr soll laufen lernen. Bauen Sie dazu einen Timer in das Uhrobjekt ein. Hinweis: Verwenden Sie folgende Seiten und die Delphi-Hilfe.
Uhr mit Ereignis Helmut Paulus Speyer, 13. 5. 09
20 Ein Ereignis für das Uhrobjekt Das Uhrobjekt soll die Ansicht über Datenänderungen informieren. Dazu wird ein Ereignis implementiert, das bei Datenänderung ausgelöst wird, also in den set-Methoden. Das Modell erhält einen Methodenzeiger, der mit einer Methode des Formulars verknüpft werden kann. Die Schritte (1) – (3) erfolgen im Modellobjekt, Schritt (4) im Formular.
Implementation des Ereignisses 21 Ereignis: On. Changed vom Typ TEreignis type TEreignis = procedure of object; (1. ) TUhr = Class . . public Methode ohne Parameterliste On. Changed : TEreignis; (2. ) …. . end; 1. Deklaration eines Methodenzeigertyps (hier: für eine Prozedur ohne Parameter) 2. Deklaration einer Referenzvariable vom Typ des Methodenzeigers
Auslösen des Ereignisses (3) 22 Modell: procedure TUhr. ticke; begin …. 3. Ereignis auslösen //GUI informieren if assigned(On. Changed) then On. Changed; (3) end; Wirkung: Das Modellobjekt ruft die mit On. Changed verknüpfte Methode des Formulars auf. Mit Hilfe der Funktion assigned() wird geprüft, ob der Methodenzeiger mit einer Methode verknüpft ist. Dieselbe Wirkung hätte die Anweisung: if On. Changed <> nil then On. Changed; Anmerkung: Mit Hilfe von Methodenzeigern kann das Modell GUI-Objekten eine Nachricht schicken (Methode aufrufen), ohne dass es diese kennt. Das Modell hat keine Referenz (Objektvariable), die auf ein GUI-Objekt zeigt!
Ereignisbearbeitungsmethode 23 GUI-Klasse: type TGUI = class(TForm) . . . private Uhr : TUhr; procedure zeit. Anzeigen; public Ereignismethode für das On. Changed-Ereignis . . . end; Verknüpfen des Methodenzeigers mit der Ereignismethode in Form. Create procedure TGUI. Form. Create(Sender: TObject); begin Uhr : = TUhr. create; //Uhrobjekt erzeugen Uhr. On. Changed : = zeit. Anzeigen; (4) end; Methodenname (keine Parameter)
Uhr mit Timer Helmut Paulus Speyer, 13. 5. 09
Uhr mit Timer 25 Das Uhrobjekt erhält eine private Timerkomponente, die Zeit im Sekundentakt erhöht. Hat - Beziehung weiter Ereignismethode für das Timer-Ereignis On. Timer Das Uhrobjekt ist für die Erzeugung und Zerstörung des Timerobjekts zuständig.
26 Implementierung uses m. TModulo. Zaehler, extctrls; type TUhr = Class wegen TTimer protected std : integer; min : integer; Sec : integer; Timer : TTimer; procedure weiter(Sender: TObject); public Objektreferenz Ereignismethode des Timers constructor create; destructor destroy; override; . . . end; Die Ereignismethode des Timers erwartet einen Parameter Sender vom Typ TObject. Daher kann die Methode ticke nicht mit dem Timerereignis On. Timer verknüpft werden. Als Timerereignismethode kommt daher die Methode weiter(Sender : TObject) hinzu, die dann ticke aufruft.
27 Erzeugung und Vernichtung des Timers constructor TUhr. create; begin Timer : = TTimer. create(nil); Erwartet wird eine Referenz auf den Besitzer der Komponente: Objekt vom Typ TComponent oder nil. with Timer do begin interval : = 1000; enabled : = true; On. Timer : = weiter Methodenzeiger mit der Ereignismethode verknüpfen end; destructor TUhr. destroy; begin Freigabe des Objekts Timer. free; inherited destroy; end; Aufruf des Destruktors der Basisklasse TObject
Vererbung - Spezialisierung Helmut Paulus Speyer, 13. 05. 09
29 Ziel Aufgabe: Zu entwickeln ist eine Uhr, die zu einer voreingestellten Uhrzeit ein Alarmzeichen ausgibt. Wünschenswert wäre, § möglichst viel von der Klasse TUhr verwenden zu können, § möglichst wenig zusätzlichen Code entwickeln zu müssen. § Codewiederholungen vermeiden zu können. Lösung durch Vererbung Eine Klasse von Objekten kann als Spezialfall einer allgemeineren Klasse definiert werden. Die Objekte der spezialisierten Klasse § verfügen über alle Merkmale und Methoden der allgemeinen Klasse, § erweitern diese aber ggf. um zusätzliche Eigenschaften (Attribute und Methoden), § können die geerbten Methoden durch Überschreiben neu definieren.
30 Vererbung - Spezialisierung Die Basisklasse TWecker als Spezialisierung der Klasse TUhr Basisklasse TUhr gemeinsamer Kern Generalisierung # timer : TTimer #!weiter(Sender : TObject) + On. Changed : TEreignis +!ticke ist ein - Beziehung TWecker abgeleitete Klasse (Unterklasse) Erweiterungen # Alarm. Min : integer # Alarm. Std : integer + On. Alarm : TEreignis Spezialisierung +!ticke In der Methode ticke soll der Alarm ausgelöst werden, falls die Alarmzeit erreicht ist; ticke wird daher in der Unterklasse erweitert. Die Basisklasse wird nicht mehr verändert!
Überschreiben einer Methode 31 procedure TUhr. ticke; begin Das Verhalten der Uhr beim Ticken wird erweitert. //Zeit erhöhen //On. Changed-Ereignis auslösen Dazu wird die ticke-Methode überschrieben. end; procedure TWecker. ticke; begin Zunächst die Methode der Basisklasse aufrufen, um das Standardverhalten auszulösen. inherited ticke; //Methode der Basisklasse Es folgen die speziellen Aktivitäten des Weckers. //Alarm auslösen, falls Alarmzeit erreicht end; Deklaration der Methode ticke als virtuelle Methode TUhr = class procedure ticke; virtual; end; TWecker = class(TUhr) procedure ticke; override; end; ticke wird in der Basisklasse mit dem Schlüsselwort virtual gekennzeichnet. ticke wird in der Unterklasse mit override gekennzeichnet und neu implementiert, damit wird die Methode überschrieben.
Verhalten virtueller Methoden 32 Problem: Welche Methode wird aufgerufen, wenn der Timer, der in TUhr deklariert ist, die Methode ticke aufruft? § Bei virtuellen Methoden wird erst zur Laufzeit entschieden, welche Methode aktiviert wird. § Der Typ des aktuellen Objekts bestimmt die Methode. Weiteres Beispiel: Mehrere Uhren unterschiedlichen Typs werden in einem Array des Basistyps gespeichert. var Uhren : Array[1. . 10] of TUhr; Je nach Objekttyp wird die passende Methode aufgerufen! for i : = 1 to 10 do Uhren[i]. ticke; Nicht virtuelle Methoden haben diese Verhalten nicht! Sie sind statisch, d. h. schon beim Compilieren wird die Methode festgelegt!
Polymorphismus 33 Das Konzept der dynamischen Bindung heißt in der OOP Polymorphismus (Vielgestaltigkeit). Merkmale n n n 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 n n Statische Methoden einer Basisklasse sollten nicht überschrieben werden. Wenn Überschreiben notwendig erscheint, sollte die Methode als virtual deklariert werden.
Aufgabe 34 1. Testen Sie das Programm ‚Wecker’ und ergänzen Sie den fehlenden Quellcode. 2. Entwickeln Sie mit Hilfe zweier Wecker eine Schachuhr Zwei Uhren, die sich gegenseitig an- und abschalten nach Prinzip: • Wenn die Partie gestartet ist, läuft die Uhr desjenigen, der am Zug ist, los. • Nachdem der Spieler seinen Zug ausgeführt hat stoppt er seine Uhr, gleichzeitig startet automatisch die Uhr des Gegners. • Jeder Spieler nur eine bestimmte Zeitspanne für die Partie zur Verfügung, die auf der Schachuhr zuvor eingestellt wird. 3. Entwickeln Sie eine Weltzeituhr. • Eine Uhr, die aktuelle Uhrzeit der verschiedenen Zeitzonen anzeigen kann. • Als Basiszeit dient dabei die Zeit am nullten Längengrad. • Die Basisuhrzeit wird festgelegt, die Uhrzeiten der anderen Zeitzonen errechnen sich durch Hinzufügen oder Abziehen einer ganzzahligen Anzahl von Stunden.
Vererbung - Generalisierung Helmut Paulus Speyer, 13. 5. 09
Bankprodukte 36 Problem: Vielfalt der Objektetypen Sie sind zwar ähnlich, aber doch verschieden sind! Depotkonto Girokonto Festgeldkonto Sparkonto Idee: • Suche nach Gemeinsamkeiten! • Organisiere sie in einer Hierarchie! • Implementiere zuerst den gemeinsamen Kern! • Implementiere dann nur noch die Unterschiede!
Vererbung 37 Girokonto Sparkonto Festgeldkonto Nummer Inhaber Stand … Kündigungsfrist Zeitraum einzahlen auszahlen … … … Unterschiedliches Verhalten: Sparkonto Ø Kündigungsfrist, kein Überziehen möglich Girokonto Ø Überweisungen, Scheck, Dispositonskredit Festgeldkonto Ø Einzahlen und Auszahlen eingeschränkt, Mindesteinlage
Vererbungshierarchie 38 Konto ist der abstrakte Oberbegriff für die drei Formen Gemeinsame Basisklasse: TKonto TSparkonto • • TGirokonto TFestgeldkonto Die Basisklasse enthält den gemeinsamen Kern. Spezialisierte Klassen werden von der Basisklasse abgeleitet; sie fügen spezielle Attribute und Operationen hinzu oder definieren bestimmte Dinge neu.
Abstrakte Methoden 39 § Die Basisklasse Konto kann die Methode auszahlen nicht sinnvoll implementieren, weil sie zu allgemein ist. § Um einen gleichartigen Aufruf der Methode zu gewährleisten, muss sie dennoch in der Basisklasse enthalten sein. (z. B. mit leeren Rumpf) § Deklariert man die virtuelle Methode der Basisklasse als abstrakte Methode, so entfällt die Implementation. procedure TKonto. auszahlen (); begin end; procedure TGirokonto. auszahlen (); procedure TSpar. Konto. auszahlen (); begin //Dispo prüfen //ist Konto gedeckt ? //Kontostand berechnen //Gebühren berechnen end;
Abstrakte Klassen 40 TKonto mit der abstrakten Methode auszahlen TKonto = class. . . procedure auszahlen; virtual; abstract; . . . end; § Implementierung in Basisklasse entfällt § Muss in allen Unterklassen überschrieben werden Kennzeichen abstrakter Klassen: 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.
41 Klassendiagramm
Aufgaben 42 1. Testen Sie das Programm ‚Konten’ und vervollständigen Sie die Auszahlungsmethoden.
Anhang 1 Helmut Paulus Speyer, 13. 05. 09
Zuweisungskompatibilität 44 Zuweisungskompatibilität Konsequenz der „ist ein“ – Beziehung: Einer Objektvariablen einer Oberklasse können Objekte aller Unterklassen zugewiesen werden. Die Umkehrung gilt nicht. Beispiel: Var uhr : TUhr; wecker : TWecker; wecker : = TWecker. create(. . . ); Möglich: Uhr : = Wecker; Uhr. set. Std(12); Nicht möglich: Uhr. set. Alarm. Std(6) Uhr ist eine Referenz auf den Teil des Weckerobjekts, der von TUhr geerbt wird. Typumwandlung: as - Operator wecker : = Uhr as TWecker; (Uhr as TWecker). set. Alarm(6); TWecker(Uhr). set. Alarm(6);
Delphis Klassenhierarchie 45 Alle Delphi-Objekte sind Nachfahren eines Urobjekts - Klasse TObject § § implementiert das grundlegende Verhalten, das allen Delphi-Objekten gemeinsam ist. (z. B. Standardkonstruktor, -destruktor) dient als Basis für einfache Objekte (keine Komponenten, keine Stream- oder Zuweisungsfunktionen) Komponenten (VCL) Alle Klassen die von TComponent abgeleitet sind heißen Komponenten, viele davon stehen in der Komponentenpalette (VCL) der Entwicklungsumgebung zur Entwurfszeit zur Verfügung. Beispiele: TForm 1 = class(Tform) - TForm 1 erweitert die vorgebene Klasse TForm TKonto = class(TObject) - Konto von TObject abgeleitet Wenn bei der Deklaration eines neuen Objekttyps kein Vorfahr angegeben wird, setzt Delphi als Vorfahr automatisch die Klasse TObject ein.
46 Delphis Klassenbibliothek (Auszug)
Anhang 2 Grundkonzepte Helmut Paulus Speyer, 13. 05. 09
Zusammenfassung OOP 48 OOP-Idee: Vorstrukturierung komplexer Systeme anhand natürlicher Objekte Jedes Objekt hat Fähigkeiten und Eigenschaften Verteilung von Aufgaben (Zuständigkeiten) Prinzipien: Objekt und Klasse Geheimnisprinzip Beziehung/Assoziation Vererbung Eine Klassen-Deklaration besteht aus Deklarationen von: Attributen für die verschiedenen Eigenschaftender Objekte Konstruktoren zur Erzeugung und Initialisierung der Objekte Methoden, d. h. Operationen (Algorithmen) auf Objekten UML-Klassendiagramm Zeigt die Klassen einer Anwendung und die Beziehungen zwischen diesen Klassen. Es liefert Informationen über den Aufbau der Anwendung. Entwurfsprinzip: Trennung von GUI und Modell (MVC)
49 Klassen und Objekte Klasse TKonto Nummer get. Konto. Stand ist Instanz von Objekte Konto 1 Konto 2 Konto 3 Nummer = 100 Nummer = 101 Nummer = 102 Stand = 10000 Stand = 2000 Stand = 5500 Klassen sind Baupläne von Objekten. Objekte sind konkrete Exemplare (Instanzen) von Klassen.
50 Geheimnisprinzip Objekte stellen Operationen/Dienste (Algorithmen) und Informationen zur Verfügung. Die innere Struktur bleibt dem Benutzer verborgen. Die Operationen (Algorithmen) auf Objekten einer Klasse heißen auch Methoden, genauer: Objekt-Methoden. abheben einzahlen Attribute – speichern den Zustand des Objekts Nummer: 101 Besitzer: Müller Stand: 1000€ Methoden – abheben, überweisen, einzahlen usw. überweisen Direkter Zugriff auf Attribute nicht möglich. Nur indirekter Zugriff mit Hilfe von Methoden (set-/get).
Modellierung der Klasse 51 UML-Klassendiagramm TKonto - Nummer : integer - Besitzer : string - Stand : double + Constructor create(. . . ); Zugriffsrechte: - privat (Zugriff nur innerhalb des Objekts) + öffentlich (Zugriff auch von außerhalb) Konstruktor (erzeugt ein Objekt) + !abheben (PBetrag: double); + !einzahlen (PBetrag: double); Aufträge (Dienste)/Prozeduren + !ueberweisen(. . . ); + ? get. Besitzer : string; + ? get. Konto. Nummer : integer; + ? get. Konto. Stand : double; Anfragen /Funktionen (Lesezugriff auf die Attribute)
Implementierung der Klasse 52 type TKonto = class private KStand : double; Zugriff von außen nicht möglich Nummer : integer; Besitzer : string; public constructor Create (PNr: integer; PBesitzer: string); procedure abheben (PBetrag: double); procedure einzahlen (PBetrag: double); procedure ueberweisen(PBetrag: double; PEKonto: TKonto); function get. Besitzer : string; function get. Konto. Nummer : integer; function get. Konto. Stand : double; end; public Zugriff von außen möglich
Konstruktoren 53 Objekte werden mit Hilfe der Konstruktoren erzeugt: constructor TKonto. create ( PNr: integer; PBesitzer: string); begin Nummer : = PNr; Besitzer : = PBesitzer; end; Der Konstruktor • legt den Speicherbereich des Objekts an, • belegt die Attribute mit Standardwerten, • gibt eine Referenz auf das erzeugte Objekt zurück. n Konstruktoren sind Klassenmethoden, d. h. sie sind nicht an ein Objekt gebunden. Beim Aufruf wird daher der Klassenname vorangestellt. n Konstruktoren haben eine Objektreferenz als Ergebnis, n aber keine Rückgabezuweisung (result : =. . . ) und folglich auch keinen Ergebnistyp. n Alle Delphiklassen besitzen einen Standardkonstruktor Create, der ersetzt wird, wenn man ihn neu implementiert.
Erzeugung von Objekten 54 var Konto 1 : TKonto; . . . Deklaration der Objektvariablen Konto 1 . . . nil Das Objekt existiert noch nicht ! Konto 1 : = TKonto. create(102, ‘Müller‘); Klassenname Wirkung: Die Objektvariable Konto 1 erhält eine Referenz (Zeiger) auf das erzeugte Kontoobjekt. Konto 1 Objekte freigeben (Speicherfreigabe) durch Aufruf eines Destruktors Konto 1. Free Destruktor Free, von TObject geerbt Nummer = 102 Besitzer = Müller Stand = 0
55 Arbeiten mit Objekten Der Zugriff auf Objekte erfolgt mit Hilfe der Objektvariablen Schema: Objektvariable. Methode Beispiel: Konto 1. abheben(500) Das GUI-Objekt ruft eine Methode des Kontoobjekts auf.
Nachricht 56 Kommunikation zwischen Objekten Konto 1. ueberweisen (400, konto 2) Das Objekt Konto 1 schickt dem Objekt Konto 2 eine Nachricht. Senderkonto 1 Empfängerkonto PEKonto. einzahlen(400) konto 2 Überweisen procedure TKonto. ueberweisen (Pbetrag : double; PEKonto : TKonto); begin abheben(PBetrag); //Betrag vom Konto abbuchen PEKonto. einzahlen(PBetrag); //Betrag auf Empfängerkonto einzahlen end;
Assoziation 57 Damit Objekte miteinander kommunizieren können, müssen Beziehungen zwischen ihnen bestehen. Kennt-Beziehung Wenn ein Objekt ein anderes Objektes aktivieren soll, muss es eine Referenz auf dieses Objekt besitzen. Dient der Kontaktaufnahme zweier autonomer Objekte Hat-Beziehung Der Besitzer hat Objekte einer anderen Klasse. Er ist für die Verwaltung (Erzeugung und Löschen) der anderen Objekte zuständig. Ein Objekt vom Typ Klasse. B ist Teil eines Objekts von Typ Klasse. A
Anhang 3 Phasen der Softwareentwicklung Helmut Paulus Speyer, 13. 05. 09
59 Software-Entwicklungsmodell Entwicklungsphasen OO-Analyse OO-Design OO-Programmierung Analyse Entwurf Codierung Modellierungskonzepte bei allen Schritten: Ø Identifizieren und Definieren von abgeschlossenen autonomen Einheiten, die Struktur und Verhalten besitzen. Ø Suchen nach Gemeinsamkeiten im Sinne der Generalisierung / Spezialisierung. Die Grenzen zwischen den Aktivitäten verschwimmen.
60 OOA - OOD - OOP OOA WAS soll das System tun? — nicht WIE § Funktionalität durch Anwendungsfälle beschreiben § Objekte (Gegenstände) und Klassen (Begriffe) identifizieren § Verantwortlichkeiten identifizieren und den Klassen zuordnen § Zusammenarbeit zwischen den Klassen identifizieren (Beziehungen) § Hierarchien definieren (Vererbung) OOD WIE soll das System arbeiten? § Verfeinern des Objektmodells (Vererbung, Abstraktion) zu einem implementierbaren Modell (Festlegung der Schnittstellen, Besonderheiten der Programmiersprache) § Anpassung des Modells an die technische Plattform, Entwicklung und Anbindung der Benutzungsoberfläche OOP Implementierung der Klassen und der Interaktionen zwischen den Objekten
Objektorientierter Entwurf 61 Wesentliches Entwurfsziel ist die Trennung Fachkonzept, Benutzungsoberfläche (GUI) und Datenhaltung. Entwicklungsphasen Reale Welt Bankkonto OO-Analyse Konto GUI Fachkonzept Datenhaltung OO-Design Ansicht Steuerung Konto. Datei OOP TGUI TKonto TFile
Anhang 3 Kursarbeit Helmut Paulus Speyer, 13. 05. 09
Kursarbeit 1 (Auszug) 63 1. Schachuhr: Dabei handelt es sich eigentlich um zwei Uhren, die sich gegenseitig an- und abschalten. Das Ganze funktioniert nach folgendem Prinzip: Wenn die Partie gestartet ist, läuft die Uhr desjenigen, der am Zug ist, los. Nachdem der Spieler seinen Zug ausgeführt hat stoppt er seine Uhr, gleichzeitig startet automatisch die Uhr des Gegners. Dabei hat jeder Spieler nur eine bestimmte Zeitspanne für die Partie zur Verfügung, die auf der Schachuhr zuvor eingestellt wird – je nach Schachform (z. B. Blitzschach oder Turnierschach) zwischen 5 Minuten und zweieinhalb Stunden. Es soll ein Programm entwickelt werden, das eine solche Schachuhr simuliert. Dazu wird die leicht modifizierte Uhrenklasse TUhr aus dem Unterricht und eine GUI-Klasse zur Analoganzeige der Zeit zur Verfügung gestellt. a) b) c) Analysiere das Klassendiagramm (siehe Dokumentation) und erläutere die verschiedenen Beziehungen zwischen den Klassen. Erläutere, in welcher Weise hier das MVC-Prinzip realisiert ist Nenne und begründe Vor- und Nachteile dieses Entwurfkonzepts. Modelliere mit Hilfe der zur Verfügung gestellten Klassen die Schachuhr. Stelle das Ergebnis in einem OOD-Klassendiagramm dar. Die Abbildung zeigt einen Prototyp. Leider hat der Programmierer noch einige wichtige Fähigkeiten der Uhrobjekte vergessen: i. die Uhren laufen noch nicht selbständig ii. bei Überschreiten der max. Spielzeit sollen die Uhren Alarm auslösen, damit das Spiel abgebrochen werden kann Erläutere, wie du die Klasse TUhr erweiterst, um die gewünschte Funktionalität zu erzielen. Gehe dabei insbesondere auf den Benachrichtigungsmechanismus ein. d) Setze deine Überlegungen um, indem du das vorgebenene Delphi-Projekt erweiterst. (Arbeit am PC) Weitere Pflichten: • • • Weiß beginnt, Schwarz startet also die Uhr. Die Bedenkzeit für jeden Spieler wird auf 5 Minuten eingestellt (nicht editierbar) Zeitüberschreitung wird angezeigt und damit das Spiel beendet.
Kursarbeit 1 (Anhang) 64 Dokumentation der Klasse "TZiffernblatt" Beschreibung der Klasse: Analoganzeige einer Uhr reagiert auf das On. Changed-Ereignis des Uhrobjekts Bezugsklasse: TImage. Objektbeziehungen TUhr (Beziehungstyp: Kennt, Kardinalität 1) Attribute my. Uhr : TUhr Referenz auf das Uhrobjekt, dessen Zeit angezeigt wird Dokumentation der Klasse "TUhr" Beschreibung der Klasse: Protokoll der Dienste / Methoden Attribute Konstruktor On. Changed : TEreignis Create(Owner : TComponent) Auftrag aktualisiere. Anzeige(uhr : TUhr) Wird ausgelöst, wenn sich die Zeit geändert hat Protokoll der Dienste / Methoden Konstruktor nachher: zeigt die aktuelle Zeit des übergebenen Uhrobjekts an constructor create (p. H: integer; p. Min: integer); Auftrag nachher: Uhr erzeugt std, min gesetzt setze. My. Uhr(uhr : TUhr) Auftrag nachher: Attribut My. Uhr ist gesetzt und On. Changed-Ereignis mit ticke() der privaten Methode aktualisiere nachher: Zeit um 1 Sekunde erhöht, On. Changed aufgerufen Auftrag zeige. Zeit(h : integer, min : integer, sec : integer) nachher: die übergebene Zeit wird angezeigt reset()
65 Kursarbeit 1 (Auszug) 2. Ampelanlage: An einer Landstraße muss der Straßenverkehr wegen Bauarbeiten zeitweilig auf eine Spur eingeschränkt und mit einer Ampelanlage geregelt werden. Ein Programm soll zwei Verkehrsampeln mit ihren Funktionen und den Straßenverkehr an der Baustelle simulieren und auf dem Bildschirm darstellen. • Jede Ampel o zeigt die Phasen ROT-ROTGELB-GRUEN-GELB nach einander mit verschiedenen Zeitdauern. o wird von einer separaten zentralen Steuerung geschaltet. • Sensoren vor den Ampeln registrieren die Anzahl der haltenden Autos und lösen einen Schaltzyklus aus. • Die Anlage soll einen einspurigen Verkehr sichern und im Dauerbetrieb laufen a) Erläutere an diesem Beispiel die einzelnen Phasen eines objektorientierten Software-Entwurfs. b) Führe eine OO-Analyse durch. Stelle deine Ergebnisse in einem Klassendiagramm dar und erläutere es kurz ( Attribute, Methoden, Beziehungen). c) Beschreibe die verschiedenen Ampelzustände mit Hilfe eines Zustandsdiagramms und entwickle für einen komplette Schaltzyklus der Steueranlage ein Aktivitätsdiagramm. d) Stell dir vor, dass du Leiter einer Arbeitsgruppe bist, die Software entwickeln soll. Nenne Teilgruppen, die du zur Lösung des Problems bilden würdest, und ordne jeder Teilgruppe Aufgaben zu.
66 Kursarbeit 2 1. Weltzeituhr Eine Weltzeituhr ist eine Uhr, die aktuelle Uhrzeit der verschiedenen Zeitzonen anzeigen kann. Als Basiszeit dient dabei die Zeit am nullten Längengrad: Die Basisuhrzeit wird festgelegt, die Uhrzeiten der anderen Zeitzonen errechnen sich durch Hinzufügen oder Abziehen einer ganzzahligen Anzahl von Stunden. Pflichten: (1) Es soll ein Programm entwickelt werden, das wie im Bild drei Weltzeituhren enthält, die Uhrzeit einer bestimmten Weltstadt (Zeitzone) anzeigen. (2) Die im Unterricht entwickelte Klasse TUhr ist zu dazu zu erweitern. (3) Die Uhren laufen nicht selbst, sondern werden synchron von außen gesteuert. Die Zeitanzeige ist digital. a) Erläutere den grundsätzlichen Unterschied zwischen der prozeduralen und der objektorientierten Programmierweise. Beziehe dich dabei auf eines der Unterrichtsprojekte. b) Analysiere das Klassendiagramm und erläutere die verschiedenen Beziehungen zwischen den Klassen. Erläutere insbesondere die Beziehung zwischen dem Uhrobjekt und der Panelkomponente! Wie wird diese Beziehung programmiertechnisch realisiert? (Anweisungen) c) Erweitere die Klasse TUhr um geeignete Attribute/Methoden und ergänze evtl. den Quellcode schon existierender Methoden so, dass die oben beschriebene Funktionalität gegeben ist. Zur Initialisierung soll ein geeigneter Konstruktor entwickelt werden. d) Begründe deine Entscheidungen kurz und stelle das Ergebnis in einem erweitereten UML-Klassendiagramm dar. e) Implementiere eine GUI mit drei laufenden Uhren wie im Bild. Verwende die Unit u. WUhr. pas. Zeitzonen: Budapest +1, Detroit – 6, Aukland +11
67 Klassendiagramm Kursarbeit 2
Kursarbeit 2 68 2. Telefonbuch In Handys oder PDAs (Personal Digital Assistant) findet man kleine Applikationen, die als Telefonbuch oder Merkzettel dienen. Diese stellen meist keinerlei Datenbankfunktionalität bereit – allerhöchstens sind sie in der Lage die Einträge zu sortieren. Man kann sie gut mit einem Karteikasten vergleichen, der eine bestimmte Sorte Karteikarten bereithält. Telefonbuch Anton Meyer 084/1234 false Betrachte ein vereinfachtes Telefonbuch, bei dem die Einträge unsortiert gespeichert werden und ihre Anzahl auf 10 begrenzt sein soll. a) Modelliere ein Telefonbuch, das mit Hilfe der Modellklassen TTelefonbuch und TEintrag aufgebaut wird. Es enthält Einträge mit den Attributen Nummer (interne automatisch erzeugte Nummerierung), Name, Telefonnummer sowie ein Ja/Nein-Feld für Kurzwahl (d. h. der Eintrag ist einer Kurzwahltaste zugeordnet). Folgende Operationen sollen möglich sein: • eine neuer Eintrag wird angelegt, dabei wird er automatisch nummeriert und • nach Angabe einer Nummer wird der zugehörige Eintrag als Zeichenkette ausgegeben. Begründe deine Entscheidungen und stelle das Ergebnis in einem UML-Klassendiagramm dar. Erläutere die Beziehung zwischen den Klassen. b) Implementiere die Konstruktoren beiden Klassen, sowie eine Methode zum Einfügen eines neuen Eintrags ins Telefonbuch. c) Erzeuge ein Telefonbuch mit maximal 10 Einträgen und füge folgende Einträge ein. [Anton, Meyer, 0675/1234, ja], [ Uwe, Ochsenknecht, 084/1234, nein] Gib auch die notwendigen Variablendeklarationen an und erläutere sie. d) Schreibe eine GUI-Methode, die das gesamte Telefonbuch (Einträge als Strings) in einer Listbox ausgibt. Verwende: die Methode Listbox. items. add( s : string) zur Ausgabe der Daten
Links und Literatur 69 E. Modrow: Informatik mit Delphi, Band 1/2, Dümmler-Stam 1998 -2000. P. Damann, J. Wemßen: Objektorientierte Programmierung mit Delphi, Band 1. Klett-Verlag 2001. U. Bänisch: Praktische Informatik mit Delphi, Band 1/2. Cornelsen 2001. Frischalowski: Delphi 5. 0, Band 1/2, Herdt-Verlag 1999. Pohl: Schülerübungen / Klausuren in Delphi, Heft 1/2, Verlag J. Pohl 1997 -2001. K. Merkert: http: //hsg. region-kaiserslautern. de/faecher/inf/material/delphi/index. php R. Mechling: http: //www. gk-informatik. de/ K. Heidler: http: //www. friedrich. fr. schule-bw. de/delphi. htm Hessischer Bildungsserver: http: //lernen. bildung. hessen. de/informatik/ Katja Weishaupt http: //lernen. bildung. hessen. de/informatik/material/weishaupt. pdf S. Spolwig: http: //oszhdl. be. schule. de/gymnasium/faecher/informatik/delphi/index. htm Daniel Garmann http: //projekte. gymnasium-odenthal. de/informatik/ Weitere Hinweise unter: http: //www. delphi-source. de Einsteiger-Tutorial http: //www. delphi-treff. de/content/tutorials/einsteigerkurs/
- Slides: 69