Home » Object Pascal » Virtuelle, dynamische und abstrakte Methoden

Virtuelle, dynamische und abstrakte Methoden

Neues Beispiel: Angenommen, wir haben eine Klasse TKoerper, die mehrere Unterklassen hat, z. B. TKugel, TQuader usw. Alle Klassen haben bestimmte Methoden gemeinsam, wie das Berechnen von Volumen und Oberfläche. Allerdings muss jede der Unterklassen eine andere Berechnung durchführen, da die Formeln für Kugeln und Quader unterschiedlich sind. Und obwohl alle Unterklassen diese gleichnamigen Methode besitzen, kann sie nicht ohne Weiteres in der Oberklasse aufgeführt werden, da hier ja keine Implementierung möglich ist (jeder rechnet anders).

Um dies aber zu ermöglichen, gibt es abstrakte Methoden. So kann z. B. in der Klasse TKoerper bereits eine function Volumen angegeben werden, die jedoch keinen Code enthält. Dieser folgt erst in den abgeleiteten Klassen. Im Code würde das so aussehen:

type
 TKoerper = class
 private
   FHoehe: real;
 public
   function Volumen: real; virtual; abstract;
   function Oberflaeche: real; virtual; abstract;
 end;

 TQuader = class(TKoerper)
 private
   FLaenge, FBreite: real;
 public
   function Volumen: real; override;
   function Oberflaeche: real; override;
 end;

implementation

function TQuader.Volumen: real;
begin
  result := FLaenge * FBreite * FHoehe;
end;

function TQuader.Oberflaeche: real;
begin
  result := (2*FLaenge*FBreite) + (2*FLaenge*FHoehe) + (2*FBreite*FHoehe);
end;

Hier ist zu sehen, dass TKoerper zwar die Methoden Volumen und Oberflaeche enthält, diese jedoch nirgends implementiert sind. Stattdessen ist dahinter virtual; abstract; vermerkt.

In der abgeleiteten Klasse TQuader dagegen sind diese beiden Methoden dann konkretisiert, jetzt ist ja bekannt, wie sie berechnet werden. Die Markierung mit override bedeutet, dass wir die Methode der Oberklasse überschreiben.
Wenn auch für weitere Unterklassen wie TKugel, TZylinder usw. so verfahren wird, dürfen für alle Objekte vom Typ TKoerper die Methoden Volumen und Oberflaeche aufgerufen werden, obwohl es nur für die konkreten Unterklassen jeweils spezifische Implementierungen gibt.

Steht in einem Code also

var K: TKoerper;

so ist K.Volumen auf jeden Fall erlaubt. Zur Laufzeit wird dann ermittelt, ob sich in K ein Objekt einer konkreten Unterklasse befindet, deren Methode dann ausgeführt wird. Handelt es sich allerdings tatsächlich um ein Objekt von TKoerper, so tritt ein Laufzeitfehler auf, weil hier Volumen ja nur abstrakt ist.

Jede abstrakte Methode muss auch als virtuell (Schlüsselwort virtual) deklariert sein. Umgekehrt muss eine virtuelle Methode nicht unbedingt abstrakt sein.

Im Unterschied zu abstrakten Methoden müssen virtuelle Methoden im betreffenden Klassentyp auch implementiert werden. Abstrakte Methoden dagegen werden nicht in der Klasse implementiert, in der sie deklariert sind.

Der Unterschied zu den „normalen“ (statisch identifizierten) Methoden besteht darin, dass virtuelle Methoden für Unterklassen (mit override) überschrieben und dadurch mit einer neuen Implementierung versehen werden können.

Wichtig:

  • Eine virtuelle Methode (egal ob abstrakt oder nicht) und die sie (durch override) überschreibende Methode müssen die gleichen Köpfe (Prozedur- bzw. Funktionsköpfe) besitzen.
  • Die überschreibende Methode ersetzt die überschriebene Methode vollständig (die überschriebene Methode steht ab der betreffenden Unterklasse nicht mehr zur Verfügung).

Dies sind große Unterschiede zum Verbergen einer Methode in einer Unterklasse durch eine andere: Zum Verbergen reicht der gleiche Methodenname (auf die Art und die Parameter und (evtl.) Ergebnistypen kommt es dabei nicht an). Außerdem kann eine verborgene Methode durch inherited wieder nutzbar gemacht werden.

Dynamische Methoden (dynamic statt virtual) werden wie virtuelle Methoden verwendet. Beide unterscheiden sich nur zur Laufzeit: Virtuelle Methoden werden auf Geschwindigkeit, dynamische auf Code-Größe optimiert. Borland empfiehlt, dynamische Methoden nur zu verwenden, wenn sich ein nachweisbarer Nutzen daraus entgibt. Im Allgemeinen ist virtual vorzuziehen.

Virtuelle Methoden verbergen: reintroduce

Wird eine als virtual deklarierte Methode verdeckt (d.h. in einer abgeleiteten Klasse wird eine gleichnamige Methode deklariert, die nicht mit der override-Direktive versehen ist), gibt der Delphi-Compiler Warnungen aus. Um die Warnung zu verhindern, wird die neue Methode, die die virtuelle Methode verdecken soll, mit reintroduce gekennzeichnet.