Programmieren - Beziehungen zwischen Objekten
Transcrição
Programmieren - Beziehungen zwischen Objekten
FB Informatik Prof. Dr. R.Nitsch Programmieren - Beziehungen zwischen Objekten • Assoziation • Aggregation • Komposition Reiner Nitsch [email protected] Überblick FB Informatik Prof. Dr. R.Nitsch • Assoziation, Aggregation und Komposition beschreiben die gemeinsame Struktur von i.d.R. langfristigen (überdauern einzelne Operationen) Beziehungen zwischen Objekten • Sie dienen der objektorientierten und semantischen Datenmodellierung. • Beispiel: Zuordnung von Teilnehmern zu Terminen im mehrbenutzerfähigen Terminkalender Objekte b1:Benutzer t1:Termin b2:Benutzer t2:Termin Links (Verweise) und … b3:Benutzer Assoziation Termin Benutzer … entsprechende Assoziation Klassen 28.10.2007 C++ - Beziehungen zwischen Objekten 2 Assoziationen und ihre Dekorationen • Assoziationen beschreiben allgemeine, lose Beziehungen zwischen Objekten (meist) unterschiedlicher Klassen. Auf Objektebene bedeutet dies, dass ein Objekt ein anderes "kennt" und mit ihm kommunizieren kann. • werden in UML-Objekt- und Klassendiagrammen durch Linien dargestellt. • sind ggf. durch zusätzliche Angaben (Dekoration) genauer beschrieben, wie z.B. durch – einen Namen , Leserichtung (`) – ggf. eine (Navigations)Richtung (→): kennen sich die beteiligten Objekte gegenseitig (Normalfall) oder kennt lediglich ein Objekt das andere? Eine Kommunikation kann immer nur von einem Objekt ausgehen, das ein anderes kennt; die Kommunikation kann dennoch bidirektional sein – Kardinalitäten (multipicity): Sie spezifiziert, wieviele andere Objekte ein bestimmtes Objekt über diese Assoziation kennen kann oder kennen muß. Kardinalitäten definieren also auch KANN oder MUSS Beziehungen. 28.10.2007 FB Informatik Prof. Dr. R.Nitsch Assoziationen in Klassendiagrammen Name Navigationsrichtung ist verheiratet mit Ehemann 1 1 unterrichtet Lehrer * Schueler KANN Bez. * hat Kunde 1,2 MUSS Bez. Konto 1..* hat Haus 1 KANN Bez. Kamin 0,1 enthaelt Eierkarton C++ - Beziehungen zwischen Objekten Ehefrau 1 Eier 6,10 Kardinalität 3 Implementierung einer bidirektionalen Assoziation FB Informatik Prof. Dr. R.Nitsch • Objekte der Klassen Frau und Mann können miteinander verheiratet sein. Dabei sollen Mann und Frau sich gegenseitig kennen und jedes ggf. die Initiative zur Kommunikation mit dem anderen Objekt ergreifen können. • Zum Verwalten der Assoziation wird i.d.R. noch eine Management-SS benötigt. Mann class Mann { Frau *pEP public: Mann() { pEP=0; ~Mann() { } void setEP(Frau void removeEP() Frau* getEP() { 0,1 ist verheiratet mit 0,1 Keine Abhängigkeit: Ehepartner lebt weiter! } *pEF) { pEP=pEF; } { pEP=0; } return pEP; } void heiraten(Frau *pF) { if(!pEP){pEP=pF; pF->setEP(this);} void scheiden() { if(pEP){ pEP->removeEP(); removeEP();} … }; 28.10.2007 Frau class Frau { Mann *pEP public: Frau() { pEP=0; ~Frau() { } void setEP(Mann void removeEP() Mann* getEP() { } *pEM) { pEP=pEM; } { pEP=0; } return pEP; } void heiraten(Mann *pM) { pEP=pM; pM->setEP(this); } void scheiden() { if(pEP){ pEP->removeEP; removeEP(); } … }; C++ - Beziehungen zwischen Objekten 4 Anwendung einer bidirektionalen Assoziation • Manager-Klassen oder -Funktionen – erzeugen und verwalten ursächlich Objekte anderer Klassen in OOProgrammen und stellen notwendige Verknüpfungen her. – treten zumeist auch in Interaktion mit dem Benutzer, um seine Wünsche auf Software-Ebene (z.B. Modus "testen" oder "spielen") – im Einklang und per Teamarbeit mit den übrigen Klassen – umzusetzen. – Jedes C++-Programm wird durch ein Hauptprogramm bzw. eine main()Funktion gestartet. In dieser Funktion wird mindestens • ein Objekt dieser ManagerKlasse erzeugt und • eine Start-Methode 28.10.2007 FB Informatik Prof. Dr. R.Nitsch class Schoepfungsgeschichte { Mann* pAdam; Frau* pEva public: Schoepfungsgeschichte() { pAdam = new Mann(); pEva = new Frau(); } void letzterAkt() { pEva->heiraten(pAdam); ApfelEssen(); Managerklasse verwaltet pAdam->scheiden(); Mann- und Frau-Objekte … auch nach der Scheidung } (keine verwaisten Objekte) void ApfelEssen() { cout << "Eva klaut einen Apfel " << "vom Baum des Hotelchefs." cout << "Mmmh… schmeckt lecker!"; cout << "Stimme vom CHEF: " << "Raus aus dem Hotel!!"; } ~Schoefungsgeschichte { delete pAdam; delete pEva; } }; void main () { aufgerufen. Schoepfungsgeschichte SG; SG.letzterAkt(); C++ - Beziehungen zwischen Objekten } 5 Aggregation FB Informatik Prof. Dr. R.Nitsch • ist ein Spezialfall einer Assoziation • beschreibt eine part-of-Beziehung: diese liegt vor, wenn Objekte einer Klasse Objekte anderer Klassen nicht nur kennen, sondern aus ihnen bestehen, d.h. es existiert eine logische Einheit: Ganzes-Teil-Beziehung (whole-part relationship, "master-slave" relationship) – Objekt A "enthält" oder "ist zusammengesetzt aus" Objekt B ⇒ Überordnungsbeziehung – Objekt B "ist Teil von" oder "gehört zu" Objekt A (Komponentenobjekt) ⇒ Unterordnungsbezhg • Erfolgt eine Operation auf einem Komponentenobjekt, so wird sie auch auf den Teilobjekten ausgeführt (Operationen mit kaskadierender Semantik). Bsp: Lesen von Platte, verschieben auf Bildschirm. • impliziert die Unabhängigkeit der Teile vom Ganzen, d.h. die Teile können auch unabhängig vom Ganzen existieren. Beispiel: Tisch (=Ganzes) und Tischbeine (=Teile). Geht Tisch kaputt, können Tischbeine ggf auch abgeschraubt, zwischengelagert und wiederverwendet werden. • ist i.d.R. einseitig navigierbar (vom Ganzen zum Teil) To-do-Liste setzt sich aus mehreren To-do-Einträgen zusammen UML-Notation ToDoEintrag * Jeder Eintrag kann in mehreren To-do-Listen vorkommen oder unabhängig von einer To-do-Liste existieren. hat gehört zu * ToDoListe UML-Symbol für Aggregation 28.10.2007 C++ - Beziehungen zwischen Objekten 6 Komposition FB Informatik Prof. Dr. R.Nitsch • ist eine (strenge) Form der Aggregation mit folgenden Einschränkungen – Ein Teil kann eine part-of-Beziehung zu genau einem Ganzen haben (implizite Exklusivität), d.h. zulässig ist nur die Kardinalität >>1<< auf der Seite des Ganzen (Aggregats) – Teilobjekte sind existenzabhängig vom Ganzen, d.h. Ganzes und Teil werden gemeinsam gelöscht – Das Ganze ist für die Verwaltung seiner Teile verantwortlich • beim Kopieren des Ganzen entstehen auch Kopien der Teilobjekte • beim Verschieben einer Eingabemaske werden auch alle Eingabefelder verschoben. – Beispiel: Buchhaltungssystem: Ein Auftrag ist existenzabhängig von einem Kunden (kein Auftrag ohne Kunde) UML-Notation Lies: • wie bei Treppe, aber • Zimmer ohne Gebäude gibt es nicht • Zimmer können auch nachträglich eingebaut werden Gebäude Komposition (Composition) 1 0..1 Aggregation Exklusivität * * Unabhängigkeit Zimmer Noch ein Beispiel: Window, Menü, Button, Scrollbar bilden eine 28.10.2007 Lies: • Jeder Kamin gehört zu höchstens einem Gebäude. • Ein Gebäude hat keinen, einen oder mehrere Kamine. • Kamine können auch ohne Gebäude existieren (Unabhängigkeit) C++ - Beziehungen zwischen Objekten Kamin Komposition 7 Beispiel: Konto FB Informatik Prof. Dr. R.Nitsch Beispiel: UML Klassendiagramm Konto hat Konto 1 1 Betrag 0..* gehört zu 1..* Kunde 1 1 1 1 Name Adresse • Die Beziehung zwischen den Klassen Kunde und Konto ist eine Assoziation, weil ein Kunde keine bis mehrere Konten haben kann, und weil ein Konto mehrere Kontoinhaber haben kann (keine Exklusivität). Kundendaten dürfen mit dem Löschen eines Kontos und Konten dürfen mit dem Löschen eines Kunden nicht automatisch gelöscht werden (keine Abhängigkeit). Eine Aggregation liegt nicht vor: ein Konto ist kein Teil eines Kunden sondern diesem lediglich zugeordnet. • Die Beziehung zwischen einem Konto-Objekt und dem Kontostands-Objekt (hier: Betrag) ist eine Komposition, weil ein Kontostand ohne zugehöriges Konto keinen Sinn ergibt. Hinweis: Ein Konto sollte natürlich nicht gelöscht werden können, solange der Kontostand nicht 0.00 ist. • Aus den selben Gründen stellt auch die Beziehung zwischen dem Kunden und seinen Adreßinformationen eine Komposition dar. 28.10.2007 C++ - Beziehungen zwischen Objekten 8 Realisierung in C++ class Kunde { string adresse; string name; vector<Konto*> kto; public: Kunde(const string& n = "", const string& a =""); ~Kunde(); void neuesKonto(const Konto &nK); void loescheKonto(const Konto &k); void displayKonten() const; hebt Zugriffschutz für Konto auf friend class Konto; }; Informatik Regel für Objekt-Konstruktor: FB Prof. Dr. R.Nitsch Zuerst werden (implizit) die Standardkonstruktoren der Teilobjekte aufgerufen: 1. string::string() für Adresse-Objekt 2. string::string() für Name-Objekt 3. vector<Konto*>::vector() für Kto-Objekt 4. Kunde::Kunde() → Aufbau von innen nach aussen // Kunde.cpp: Implementierung der Klasse Kunde. #include "Kunde.h" #include <iostream> using std::cout; using std::endl; Kunde string adresse string name vector<Konto*> kto Konstruktor Kunde::Kunde (const string& n, const string& a) { name=n , adresse=a; } Kunde::~Kunde () { } Destruktor void Kunde::neuesKonto(const Konto& nK) { kto.push_back(&nK); } void Kunde::loescheKonto(const Konto& k) { /*in kto &k suchen und löschen*/ } void Kunde::displayKonten() const { displayKunde(); cout << " hat folgende Konten: " << endl; for ( int i=0; i < kto.size(); cout << kto[i]->getNummer() << ' ', i++ ); cout << endl; } 28.10.2007 C++ - Beziehungen zwischen Objekten 10 Realisierung in C++ FB Informatik Prof. Dr. R.Nitsch class Betrag Komp. od. Aggr? Komposition { int euro, cent; void set( int e, int c = 0) Private! public: Betrag( int e, int c); void display() const; friend class Konto; für Zugriff auf private } Elemente // Betrag.cpp: // Implementierung der Klasse Betrag. #include "Betrag.h" #include <iostream> Betrag::Betrag( int e, int c) Konstruktor { euro=e; cent=c; } Betrag::~Betrag () {} Destruktor Ausgabe: 3.50 void Betrag::display() const { cout << euro << '.' << cent << endl; } void Betrag::set( int e, int c) { euro=e; cent=c; } 28.10.2007 C++ - Beziehungen zwischen Objekten 11 Realisierung in C++ Komposition mit Kardinalität 1 Attribut Betrag und Konto haben die gleiche Lebensdauer class Konto { Betrag stand; long nummer; Kunde *pKunde; public: Assoziation… Konto( long nr, Kunde *pK); void druckeAuszug() const; void einzahlen( int e, int c = 0); long getNummer() const { return nummer; } // … SS für Aggregationsmanagement }; FB Informatik Prof. Dr. R.Nitsch …mit Kardinalität 1 Regel für Objekt-Konstruktor: // Konto.cpp: Implementierung der Klasse Konto. Zuerst werden (implizit) die Standard#include "Konto.h" Konstruktoren der Teilobjekte aufgerufen Konto::Konto ( long nr; Kunde *pK) {: Stand(0,0) { → Aufbau von innen nach aussen nummer = nr; if(pK) pKunde=pK else exit(1); stand.set(0,0); Konto Fehler: Standardkonstruktor fehlt! } → Implementieren oder Betrag Konto::~Konto() {} besser: expliziter void Konto::druckeAuszug() const { Euro Konstruktoraufruf in pKunde->display(); Cent Vorinitialisierungsliste stand.display(); Nummer } pKunde void Konto::einzahlen( int e, int c ) { if (e>=0 && c>=0) { c += stand.getCent(); stand.set(stand.getEuro()+e+c/100 , c%100); set ist private! Deshalb: friend class Konto } in Klasse Betrag 12 C++ - Beziehungen zwischen Objekten } 28.10.2007 Realisierung in C++ FB Informatik Prof. Dr. R.Nitsch // Anwendungsumgebung void main() { //Objekt vom Typ Kunde dynamisch erzeugen Kunde* pK1 = new Kunde("Meier","Darmstadt"); Konto Kto1(123, pK1), Kto2(456, pK1); Kto1.einzahlen(100,99); Kto1.einzahlen(100,99); Kto1.druckeAuszug(); Kto2.einzahlen(1000); Kto2.druckeAuszug(); pK1->displayKonten(); } Kann auch von einer Manager-Klasse (z.B. Kontenverwaltung) übernommen werden Ausgabe: KontoNr 123 Kontostand: 201.98 KontoNr 456 Kontostand: 1000.0 Meier aus Darmstadt hat folgende Konten: 123 456 Press any key to continue 28.10.2007 C++ - Beziehungen zwischen Objekten 13