Objektorientierte Programmierung - Kapitel 5 - Objekt-Beziehungen
Inhalte von Dr. E. Nadobnyh
51. Verbindungen zwischen Objekten in C++
Nachricht
Ein objektorientiertes Programm ist eine Vielzahl kooperierender Objekte.
Kommunikation zwischen Objekten bedeutet, dass die Objekte sich gegenseitig Nachrichten schicken, d.h. Methoden des anderen Objektes aufrufen.
Verbindungen zwischen Objekten in C++
Die Voraussetzung für eine Kommunikation zwischen Objekten ist , dass diese sich kennen. Eine C++ -Methode kennt folgende Objekte:
1) Globale Objekte,
2) Lokale Objekte,
3) Parameter-Objekte,
4) Attribut-Objekte.
Objekte können in drei bekannten Formen gestaltet werden:
1) Benanntes-Objekt,
2) Referenziertes Objekt ,
3) Referenz-Objekt.
Subobjekte
Objekte können sich aus anderen Objekten (AttributObjekten) zusammensetzen.
Ein Attribut-Objekt wird auch als Subobjekt bezeichnet.
Es gibt zwei Arten von Subobjekten:
1) Teilobjekt (Benanntes-Objekt ),
2) Eigenständiges Subobjekt (Referenziertes Objekt ).
Begriffsverwirrung: Ein Subobjekt kann manchmal als ein Teilobjekt bezeichnet werden.
Ein Teilobjekt ist ein unlösbares Subobjekt.
class A{ };
class B{ A a1; };
main(){ B b1; }
Hier ist a1 das Teilobjekt des Objektes b1.
Bei der Initialisierung eines Objektes, das Teilobjekte enthält, sind mehrere Konstruktoren auszuführen.
Reihenfolge der Konstruktor- Aufrufe:
1) Zuerst werden die Teilobjekte angelegt und initialisiert. Ohne weitere Angaben wird für jedes Teilobjekt der Default- Konstruktor aufgerufen.
2) Danach wird der Konstruktor des Objektes aufgerufen.
Der Aufruf von Default-Konstruktoren beim Aufbau von Teilobjekten hat folgende Nachteile:
1) Ein Teilobjekt wird zwei mal mit Werten versehen: zuerst durch den Aufruf des Default-Konstruktors des Teilobjektes, danach durch die Zuweisung beim Aufruf des Konstruktors des Objektes. Diese doppelte Aktion beeinträchtigt die Ausführungszeit.
2) Konstante Objekte oder Referenzen können nicht durch die Zuweisung mit Werten versehen werden.
3) Klassen ohne Default-Konstruktor können nicht als Typ für Teilobjekte verwendet werden.
Initialisierungsliste
Eine Initialisierungsliste dient für die direkte Initialisierung von Teilobjekten. Diese Liste wird hinter dem Kopf des Konstruktors, durch einen Doppelpunkt getrennt, angegeben. Eine Initialisierungsliste besteht aus den Namen der Teilobjekten und seinen Anfangswerten.
⇒ Demo 1
5.2. Beziehungen zwischen Objekten und ihre Umsetzung in C++
Beziehungen
Man unterscheidet grundsätzlich drei Arten von Beziehungen:
1) Beziehungen zwischen Klassen und Objekten
Die Objekte, die zu einer Klasse gehören, werden als Exemplare (Instanze) dieser Klasse bezeichnet.
2) Beziehungen zwischen Klassen
Diese Beziehung wird durch Vererbung definiert. Die abgeleitete Klasse steht zur Basisklasse in einer Ist-Beziehung.
3 )Beziehungen zwischen Objekten
Objekte stehen in Beziehungen, wenn sie sich kennen. Ein Objekt steht in einer Hat-Beziehung zu anderem, wenn es das anderen Objekt als Attribut besitzt.
Beziehungen in UML
UML (Unified Modeling Language) ist eine Sprache, um objektorientierte Systeme zu beschreiben.
Die Ergebnisse der objektorientierten Analyse (OOA) und des objektorientierten Designs (OOD) können in einer normierten Form beschrieben werden. Damit können Analyse- und Entwurfsfehler z.B. noch vor der Implementierung entdeckt werden.
⇒ Demo 2
Arten von Objekt-Beziehungen
Die Arten sind in der UML unabhängig von konkreter Programmiersprache standardisiert:
1) Einfache Assoziation
2) Aggregation
3) Komposition
Objekt-Beziehungen werden ganz allgemein auch Assoziation genannt.
Die einfache Assoziation (auch Benutzt-Beziehung) bedeutet gleichrangige Beziehung zwischen Objekten.
UML- Klassendiagramm für unidirektionale Assoziation:
Ein Objekt der Klasse „Beruf“ kennt ein anderes Objekt der Klasse „Werkzeug“.
Obwohl in UML eine Assoziation als eine Linie zwischen den Klassenkästchen dargestellt wird, ist eine Assoziation eine Beziehung zwischen Objekten – den Exemplaren dieser Klassen.
Die einfache Assoziation kann in C++ umgesetzt sein:
1) als ein lokales Objekt,
2) als Parameterobjekt,
3) als referenziertes Attribut-Objekt
Beispiel:
Ein lokales Objekt der Klasse „Werkzeug“ wird in einer Methode der Klasse „Beruf“ angelegt:
class Werkzeug { public: void g(){ } };
class Beruf
{ public: void p(){ Werkzeug w1; w1.g(); }
};
class Beruf
{ public: void p(){ Werkzeug w1; w1.g(); }
};
⇒ Demo 3
UML- Klassendiagramm für die bidirektionale Assoziation:
Objekte kennen sich gegenseitig. Im Beispiel sind beide Objekte als referenzierte Attribute repräsentiert.
class ABT //Abteilung
{ ANG* g;
public:
void link(ANG* );
void unlink(ANG* );
};
class ANG //Angestellter
{ ABT* t;
public:
void link(ABT* );
void unlink(ABT* );
};
{ ANG* g;
public:
void link(ANG* );
void unlink(ANG* );
};
class ANG //Angestellter
{ ABT* t;
public:
void link(ABT* );
void unlink(ABT* );
};
UML- Klassendiagramm für die reflexive Assoziation:
Eine reflexive Assoziation besteht zwischen Objekten derselben Klasse. Dabei müssen immer die Rollennamen angegeben werden.
class Person
{ Person* partner; //als referenzierter Attribut
public:
void setPartner( Person* p){ ... ; partner=p; }
};
{ Person* partner; //als referenzierter Attribut
public:
void setPartner( Person* p){ ... ; partner=p; }
};
⇒ Demo 4
UML- Klassendiagramm für die Aggregation:
Die Aggregation bedeutet hierarchische Beziehung zwischen Objekten. Ein Objekt ist Teil eines anderen. Keine gleichwertige Beziehung. Auf der Seite des Aggregates (des Ganzen) wird eine Raute gezeichnet.
Die Aggregation wird auch Teil-Ganze-Beziehung, Hat-Beziehung, Enthalten- Beziehung genannt.
Die Teile können unabhängig vom Aggregat erzeugt werden. Die Lebensdauer der Teile kann dabei länger sein als die Lebensdauer des Aggregates.
Ein Beispiel für eine Aggregation ist die Beziehung zwischen einer Mannschaft und ihren Spielern. Ein Mensch kann in mehreren Mannschaften spielen, und wird eine Mannschaft aufgelöst, bedeutet es in den allermeisten Fällen nicht das Ende für ihre Ex-Spieler.
Die Aggregation kann in C++ als referenziertes Attribut-Objekt umgesetzt sein.
class Firma
{ Mitarbeiter* mit[4]; //einfache Datenstruktur
public:
void eingestellt(Mitarbeiter & ma)
{ ... ; mit[...] = & ma;
}
};
{ Mitarbeiter* mit[4]; //einfache Datenstruktur
public:
void eingestellt(Mitarbeiter & ma)
{ ... ; mit[...] = & ma;
}
};
⇒ Demo 5
UML- Klassendiagramm für die Aggregation und unidirektionale Assoziation:
In diesem Beispiel hat jeder Mitarbeiter eine neue Möglichkeit eine Differenz zwischen seinem und durchschnittlichem Lohn zu berechnen.
class Mitarbeiter
{ float lohn;
Firma* fa; //neue Assoziation
public:
float differenz(){ return lohn - fa->durchschn();}
};
{ float lohn;
Firma* fa; //neue Assoziation
public:
float differenz(){ return lohn - fa->durchschn();}
};
⇒ Demo 6
UML- Klassendiagramm für die Komposition:
Auf der Seite des Ganzen wird eine gefüllte Raute gezeichnet.
Komposition bedeutet, daß die Teile vom Ganzen existenzabhängig sind. Beim Entfernen des Ganzen werden alle Teile automatisch entfernt.
Eine Komposition ist eine starke Form der Aggregation. Der Zugriff und das Erzeugen der Teile erfolgen immer über das Aggregatobjekt.
Die Komposition kann in C++ in folgenden Varianten umgesetzt sein:
1) als benanntes Attribut-Objekt (ein echtes physisches Enthaltensein):
class Kopf{};
class Mensch{ Kopf k1;};
class Mensch{ Kopf k1;};
2) als referenziertes Attribut-Objekt:
class GN{ }; //Geheimnummer
class Konto
{ GN* num;
public:
Konto(){num= new GN;}
~Konto(){delete num;}
};
class Konto
{ GN* num;
public:
Konto(){num= new GN;}
~Konto(){delete num;}
};
CategoryObjektorientierteProgrammierung