Home » Object Pascal » Vererbung

Vererbung

Wir kommen nun zu einem wichtigen Punkt beim Arbeiten mit Klassen: der Vererbung.

Bisher haben wir unsere Klassen aus dem „Nichts“ komplett neu aufgebaut. Dennoch kannten sie bereits einige vordefinierte Befehle, die wir nicht programmiert haben wie z.B. create und destroy. Das liegt daran, dass in Delphi alle Klassen automatisch Nachkommen von TObject sind. Und wie im wirklichen Leben erben die Nachkommen das Verhalten ihrer Vorfahren.

Wird also ein Befehl an einer Instanz aufgerufen, der in der Klasse gar nicht definiert ist, sieht der Compiler beim direkten Vorfahren der Klasse nach usw., bis er den Befehl findet. Taucht er bei keinem der Vorfahren bis TObject auf, gibt es eine Fehlermeldung. Natürlich betrifft das nicht nur Methoden, sondern auch Attribute und Eigenschaften.

Wozu das Ganze gut sein kann, soll das folgende Beispiel zeigen.

type TMensch = class  //entspricht class(TObject)
 private
   FVorname: string;
   FNachname: string;
   FGeburtstag: TDate;
   FGeschlecht: string;
 end;

 TBerufstaetig = class(TMensch)
 private
   FKontoNr: integer;
   FBankleitzahl: integer;
 public
   procedure GehaltZahlen;
 end;

 TManager = class(TBerufstaetig)
 private
   FGehalt: real;
   FZulagen: real;
   FAnzahlMitarbeiter: integer;
 end;

 TSchueler = class(TMensch)
 private
   FKlasse: integer;
   FTaschengeld: real;
 end;

Hinter dem Schlüsselwort class steht in Klammern der Name des direkten Vorfahren. TBerufstaetig erbt also alle Attribute wie FVorname und FNachname von der Klasse TMensch und fügt noch eigene Attribute hinzu, die eben nur für Berufstätige gebraucht werden. TManager erbt von TBerufstaetig und somit auch von TMensch.

Wird von TManager eine Instanz gebildet

var Chef: TManager;
...
Chef := TManager.Create;

sind alle folgenden Aufrufe möglich:

Chef.FNachname := 'Schmidt';
Chef.FBankleitzahl := 12345670;
Chef.FGehalt := 10000;

obwohl alle drei Attribute in verschiedenen Klassen deklariert wurden.
Steht hinter dem Schlüsselwort keine Klasse (wie bei TMensch), wird TObject als direkter Vorfahr genommen.
Im Prinzip gilt: Alle Gemeinsamkeiten werden in einer Oberklasse (Basisklasse) zusammengefasst. Die Nachfahren (abgeleitete Klassen) enthalten dann nur noch Methoden und Attribute, in denen sie sich unterscheiden. Gäbe es keine Vererbung, müssten lauter gleichrangige Klassen erstellt werden, die größtenteils den gleichen Code enthalten.

Versiegelte Klassen

Ab Delphi 2009In Delphi gibt es die Möglichkeit, dass ein Entwickler festlegen kann, dass eine Klasse nicht weiter abgeleitet werden darf. Dafür kennzeichnet er die betroffene Klasse als sealed (versiegelt):

 TSchueler = class sealed (TMensch)
 private
   FKlasse: integer;
   FTaschengeld: real;
 end;

Zuweisungskompatibilität von Objektreferenzen

Wie schon im Teil „Zugriff auf Objekte“ gesehen, ist das Zuweisen von Objektreferenzen möglich (auto1 := auto2). In diesem Fall waren beide Instanzen der gleichen Klasse. Kommt Vererbung ins Spiel, wird die Sache etwas komplizierter. Folgendes ist bei Zuweisungen möglich:

  • Beide Seiten besitzen denselben Klassentyp (auto1 := auto2)
  • Die rechte Seite referenziert einen Nachkommen der linken Seite. Beispiel:
var m: TMensch;
 s: TSchueler;
...
m := s;

Andere Varianten sind nicht möglich! Wenn die Typen ungleich sind, muss die rechte Seite eine Präzisierung der linken Seite sein. An dieser Stelle mag man denken: Wie kann das denn funktionieren? Die Präzisierung hat doch häufig mehr Daten als die Basisklasse, wieso kann man sie dann zuweisen? Das liegt daran, dass wir es hier eben nur mit den Objektreferenzen zu tun habe. Diese sind genau genommen nur Variablen, die eine Zahl beinhalten, nämlich eine Adresse im Hauptspeicher. Die Variablen an sich sind also Zeiger und beinhalten alle die gleiche Datenmenge, nämlich eine Adresse. Deshalb funktioniert die Zuweisung.