![]() |
||
| OOP |
Objekt
Ereignisse
Interface
|
|
|
Polymorphie von Methoden |
Angenommen, wir haben zwei Zeiger oA und oB auf Objekte vom Typ TA und TB. Beide haben die Methode 'tuewas', die aber durchaus Verschiedenes tun können. Wie unterscheidet der Compiler zwischen den beiden gleichlautenden Methoden?
Klar, nach dem Typ! Die Bindung zwischen der Variablen oA und der Methode tuewas wird nach dem Typ von oA zur Compilierzeit bestimmt. Man redet von früher Bindung oder statischer Bindung.
An dem UML-Klassendiagramm sieht man, dass die Methode wuerfele dreimal auftaucht.
In einem kleinen Programm (vererbung3.zip)
sollen nun die verschiedenen Fälle, zwischen den Methoden zu unterscheiden, untersucht werden.
.......
type
TW = class(tObject)
private
FZahl : integer;
public
procedure SetZahl(a : integer);
function GetZahl : integer;
procedure wuerfele;
end;
TW4 = class(TW)
public
procedure wuerfele;
end;
TW6 = class(TW)
public
procedure wuerfele;
end;
.......
implementation
........
procedure TW.wuerfele;
begin
setZahl(0);
end;
procedure TW4.wuerfele;
begin
setZahl(Random(4)+1);
end;
procedure TW6.wuerfele;
begin
setZahl(Random(6)+1);
end;
Man kann w vom Typ TW mit w4, w6 oder wA belegen, immer wird mit w.wuerfele nur die Methode wuerfele1 aufgerufen (als Augenzahl wird 0 ausgegeben).
.......
type
TW = class(tObject)
private
FZahl : integer;
public
procedure SetZahl(a : integer);
function GetZahl : integer;
procedure wuerfele; virtual; // legt VMT an
end;
TW4 = class(TW)
public
procedure wuerfele; override; // bewirkt Eintrag in VMT
end;
TW6 = class(TW)
public
procedure wuerfele; override; // bewirkt Eintrag in VMT
end;
Das Schlüsselwort virtual bewirkt das Anlegen einer sogenannten virtuellen Methoden-Tabelle VMT
| Typ | Adresse der wuerfele-Methode |
| TW | wuerfele1 |
Mit dem Schlüsselwort override wird jeweils ein Eintrag in die VMT hinzugefügt.
| Typ | Adresse der wuerfele-Methode |
| TW | wuerfele1 |
| TW4 | wuerfele2 |
| TW6 | wuerfele3 |
Jetzt wird bei jedem Aufruf zuerst der Typ der Belegung der polymorphen Variablen w bestimmt und aus der VMT die "richtige" wuerfele-Methode herausgesucht. Dh. die Bindung zwischen Variable und Methode wird erst während der Laufzeit ermittelt und kann sich natürlich auch während der Laufzeit änderen. Man spricht von später Bindung bzw. von polymorphen Methoden.
Ein Test zeigt die Richtigkeit der Überlegungen.
Es ist außerdem instruktiv, die Schlüsselwörter virtual bzw. override vorübergehend wegzulassen und die Auswirkungen zu studieren.
Im Beispiel erzeugte die Methode wuerfele in TW eine Augenzahl 0. Das war für obige Experimente ganz nützlich, ist aber im Allgemeinen sinnlos. Eigentlich sollte wuerfele in TW gar nichts tun. Gut, das läßt sich mit einem leeren Prozedurrumpf erreichen. Besser ist es, in diesem Fall durch das Schlüsselwort abstract anzuzeigen, dass eigentlich nur eine VMT angelegt werden soll, aber kein Aufruf der "allgemeinen" wuerfele-Methode vorgesehen ist. In diesem Fall entfällt natürlich auch die unnötig gewordene Implementierung.
type
TW = class(tObject)
private
FZahl : integer;
public
procedure SetZahl(a : integer);
function GetZahl : integer;
procedure wuerfele; virtual; abstract; // legt nur VMT an
end;
Schreibe ein Programm, in dem die Objekte Claudia, Felix, Sven und Torsten einer Referenzvariablen
Mensch vom Typ TMensch zugeordnet werden können. Außerdem soll man Mensch nach seinem Typ
fragen können.
aus einem 'Informatik-Western':
if (mensch is TMann) then (mensch as TMann).handle;
Frei übersetzt: "Wenn du ein Mann bist, so handle auch wie ein Mann!"
Herr Paulus hat eine hilfreiche Präsentation (D2-Paulus-OOPVererbung.zip) zum Thema verfasst.