42
Polymorphie (Vielgestaltigke it)

Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Embed Size (px)

Citation preview

Page 1: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Polymorphie(Vielgestaltigkeit)

Page 2: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen wie z.B. Rechtecke oder das andere Mal Kreise auf dem Bildschirm ausgeben bzw. zeichnen kann), dann nennt man dies Polymorphie

Page 3: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Beispiel:In einem Feld sollen verschiedene Objekte (entweder Rechtecke oder Kreise) abgespeichert und dann (z.B. zu Testzwecken) deren spezifischen Daten (Länge und Breite bzw. Radius) ausgegeben werden

Page 4: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Die Reihenfolge der Objekte (Rechteck bzw. Kreis) in dem Feld soll vom Anwender bestimmt werden bzw. zufällig sein.

Page 5: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Aber Halt:In einem Feld können nur Objekte der gleichen Klasse gespeichert werden.

Page 6: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Deswegen muß man eine Oberklasse von Rechteck und Kreis erzeugen und Objekte (genauer Pointer; siehe später) der Oberklasse Objekte der Unterklassen Rechteck oder Kreis zuweisen und die Objekte der Oberklasse im Feld speichern.

Page 7: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Vorgehensweise:Man erzeugt die Klassen Rechteck und Kreis mit jeweils der spezifischen print Funktion, die den Flächeninhalt und den Umfang des Rechtecks bzw. des Kreises ausgibt.

Page 8: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Dann erzeugt man eine gemeinsame Basisklasse, z.B. mit dem Namen Form der Klassen Rechteck und Kreis.

Page 9: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

In UML-Darstellung:

Page 10: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Form

Rechteck Kreis

Page 11: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Mit new werden (in einer Schleife) jeweils Pointer auf ein Rechteck bzw. einen Kreis erzeugt und einem Pointer auf Form zugewiesen und dieser Pointer in einem Element des Feldes abgespeichert.

Page 12: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Als Programm-Skizze

Page 13: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Bemerkung:Der Einfachheit halber ist die Reihenfolge der Rechtecke bzw. Kreise in der folgenden Programm-Skizze nicht zufällig bzw. vom Anwender vorgegeben und außerdem ist die Schleife weggelassen worden.

Page 14: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Form *f[10];Kreis *kp;Rechteck *rp;

kp = new Kreis();rp = new Rechteck();

f[0] = rp;f[1] = kp;

f[0]->print();f[1]->print();

Einem Pointer auf Form wird ein Pointer auf Rechteck zugewiesen

Einem Pointer auf Form wird ein Pointer auf Kreis zugewiesen

Die print() Methode wird aufgerufen, die in der Klasse Rechteck implementiert wurde.

Die print() Methode wird aufgerufen, die in der Klasse Kreis implementiert wurde.

Dazu muß print als virtuelle Funktion deklariert werden, d.h. der Name print wird an die Funktion nicht während der Kompilierung gebunden, sondern während der Laufzeit

Page 15: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Das exakte Programm:

Page 16: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

#include "stdafx.h"#include <iostream>#include <time.h>

using namespace std;

Page 17: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

class Form{ public: virtual void print();}; // Form

class Rechteck: public Form{ private: double l; double b;

public: Rechteck(double ll, double bb); ~Rechteck(); virtual void print();}; // Rechteck

Durch den Bezeichner virtual wird print eine virtuelle Funktion. Die Verwendung von virtual ist nur innerhalb einer Klassendeklaration zulässig.

Der Bezeichner virtual vererbt sich und muß daher nicht mehr (kann aber) in den Subklassen wiederholt zu werden.

Page 18: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

class Kreis: public Form{ private: double r;

public: Kreis(double rr); ~Kreis(); virtual void print();}; // Kreis

Der Bezeichner virtual vererbt sich und muß daher nicht mehr (kann aber) in den Subklassen wiederholt zu werden.

Page 19: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

void Form::print(){};

Rechteck::Rechteck(double ll, double bb){ l = ll; b = bb;};

Rechteck::~Rechteck(){};

void Rechteck::print(){ cout << "Rechteck: Laenge =" << l << " Breite =" << b;};

print wird in der Klasse Rechteck redefiniert (neu implementiert).

Page 20: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Kreis::Kreis(double rr){ r = rr;}

Kreis::~Kreis(){}

void Kreis::print(){ cout << "Kreis: Radius = " << r << endl;}

print wird in der Klasse Kreis redefiniert (neu implementiert).

Page 21: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

int main(){ int r,i; Form *v[10];

srand((unsigned)time(NULL));

for(i=0;i<10;i++){ r = rand()%2; if(r==0) v[i] = new Kreis(100*i); else v[i] = new Rechteck(10*i, 20*i); }

Es wird ein Feld v mit 10 Pointern auf Objekte der Klasse Form reserviert.

r ist eine Zufallszahl, die entweder den Wert 0 oder 1 annimmt.

legt ein Objekt der Klasse Kreis an, liefert einen Pointer darauf zurück und weist ihn einem Feldelement (pointer auf Form) zu.

Dies funktioniert, weil: "Oberklasse = Unterklasse" korrekt ist.

legt ein Objekt der Klasse Kreis an, liefert einen Pointer darauf zurück .

Page 22: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

for(i=0;i<10;i++){ v[i]->print();

}

for(i=0;i<10;i++){ delete v[i];

} return(0);}

delete gibt den dynamisch erzeugten Speicher wieder frei.

Gibt jeweils den Radius des Kreises eines Feldelements bzw. Breite und Länge des Rechtecks aus.

Page 23: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Frage:Wäre das folgende abgeänderte Programm auch korrekt ?

Bem:Im Vergleich zum letzten Programm wurde nur der rot gekennzeichnete Quellcode in main() geändert.Alles andere ist gleich.

Page 24: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

void main(){ int r; int i; Form vv[10];

srand((unsigned)time(NULL));

Es wird ein Feld vv mit 10 Objekten der Klasse Form reserviert.

Page 25: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

for(i=0;i<10;i++){ Rechteck re(10*i, 20*i); Kreis kr(100*i); r = rand()%2; if(r==0) vv[i] = kr; else vv[i] = re;

}

for(i=0;i<10;i++) vv[i].print();}

legt bei jedem Durchgang ein Objekt der Klasse Kreis an.

Späte Bindung funktioniert nur, wenn der Zugriff über einen Pointer auf ein Objekt der Basisklasse erfolgt. Da dies hier nicht der Fall ist, wird die frühe Bindung verwendet. Der Typ der Variablen vv (also Form) bestimmt, welche print()-Funktion aufgerufen wird. Diese print()-Funktion der Klasse Form gibt aber nichts auf dem Bildschirm aus.

legt bei jedem Durchgang ein Objekt der Klasse Rechteck an.

Page 26: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Rein virtuelle Funktionen auch pure function (englisch) oderabstrakte Funktionen genannt

Page 27: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Motivation

Page 28: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Hat es Sinn, im letzten Programm eine Instanz der Klasse Form zu bilden ?

Nein, die Klasse Form ist nur dazu da, eine Basisklasse der Klassen Rechteck und Kreis zu bilden. Die Klasse Form besitzt nicht einmal ein Attribut, sondern nur die Methode print(), die nichts macht.

Page 29: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Was passiert, wenn der Programmierer aus Versehen vergessen hat, in einer der Subklassen, z.B. Rechteck, die print() Methode zu deklarieren und zu definieren (implementieren) ?

Dann wird die virtuelle Funktion print() der Basisklasse in die Subklasse Rechteck vererbt. Ein Aufruf der Funktion print() der Klasse Rechteck macht dann also das gleiche wie ein Aufruf der Funktion print() der Klasse Form (nämlich gar nichts, weil sie keine Anweisungen besitzt).

Page 30: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Um zu verhindern, daß 1) Instanzen einer Klasse gebildet werden und um zu verhindern, daß 2) ein Programmierer vergisst, eine virtuelle Funktion in einer Subklasse zu deklarieren und zu definieren (implementieren), wurden die sogenannten rein virtuellen Funktionen eingeführt.

Page 31: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Eine rein virtuelle Funktion (abstrakte Funktion) ist eine virtuelle Funktion mit dem Zusatz =0

Beispiel:virtual print()=0;

Das =0 bedeutet: Diese Funktion muss nicht (kann aber) in der Klasse implementiert werden.

Page 32: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Besitzt eine Klasse mindestens eine abstrakte Funktion (rein virtuelle Funktion), dann heißt diese Klasse abstrakte Klasse. Von dieser darf dann keine Instanz gebildet werden (wohl aber Pointer auf Objekte dieser abstrakten Klasse).

Page 33: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Was muss man im letzten Programm abändern, damit sichergestellt wird, daß von der Klasse Form keine Instanz gebildet werden kann ?

Die Programmierzeile:virtual void print();in der Klasse Form muß ersetzt werden durch:virtual void print()=0;

Page 34: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Was passiert, wenn der Programmierer im letzten Programm aus Versehen vergessen hat, in einer der Subklassen, z.B. Rechteck, die print() Methode zu deklarieren und zu definieren (implementieren) ?

Page 35: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Hier nochmals das Programm:

Page 36: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

#include "stdafx.h"#include <stdlib.h>#include <stdio.h>#include <time.h>

Page 37: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

class Form{ public: virtual void print()=0;}; // Form

class Rechteck: public Form{ private: double l; double b;

public: Rechteck(double ll, double bb); ~Rechteck(); // virtual void print();}; // Rechteck

Durch die Bezeichnung = 0 wird eine rein virtuelle Funktion deklariert.

Es wurde "vergessen", print() zu deklarieren

Page 38: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

class Kreis: public Form{ private: double r;

public: Kreis(double rr); ~Kreis(); virtual void print();}; // Kreis

Alles wie im letzten Programm (nichts wurde verändert).

Page 39: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

// void Form::print(){// };

Rechteck::Rechteck(double ll, double bb){ l = ll; b = bb;};

Rechteck::~Rechteck(){};/*void Rechteck::print(){ cout << "Rechteck: Laenge =" << l << " Breite =" << b;}; */

Es wurde "vergessen", print() zu definieren (implementieren)print() braucht in Form nicht mehr

implementiert zu werden.

Page 40: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

Kreis::Kreis(double rr){ r = rr;}

Kreis::~Kreis(){}

void Kreis::print(){ cout << "Kreis: Radius = " << r << endl;}

Alles wie im letzten Programm (nichts wurde verändert).

Page 41: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

void main(){ int r,i; Form *v[10];

srand((unsigned)time(NULL));

for(i=0;i<10;i++){ r = rand()%2; if(r==0) v[i] = new Kreis(100*i); else v[i] = new Rechteck(10*i, 20*i); }

Aber was meint der Compiler dazu, daß ein Objekt der Klasse Rechteck angelegt wird ?

Alles wie im letzten Programm (nichts wurde verändert).

Da die print() Funktion in der Klasse Rechteck fehlt (und damit nicht redefiniert wird), erbt Rechteck von Form die rein virtuelle Funktion print(). Da dann Rechteck eine rein virtuelle Funktion besitzt, kann auch keine Instanz von Rechteck erzeugt werden --> Compiler meldet Fehler. Damit kann der vergessliche Programmierer gezwungen werden, die Funktion print() in den Subklassen zu implementieren.

Page 42: Polymorphie (Vielgestaltigkeit). Wenn eine Methode, wie z.B. print für verschiedene Programmteile steht (und z.B. einmal Objekte verschiedener Klassen

for(i=0;i<10;i++){ v[i]->print();

}

for(i=0;i<10;i++){ delete v[i];

}}

Alles wie im letzten Programm (nichts wurde verändert).