Polymorphie von Methoden
Erinnerung:
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.
Experimentiermodell
|
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. |
Statische, frühe Bindung
.......
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 mit w4, w6 oder wA belegen, immer wird mit w.wuerfele nur die Methode wuerfele1
aufgerufen (als Augenzahl wird 0 ausgegeben).
Dynamische, späte Bindung
.......
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.
Abstrakte Methoden
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;
|