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