Klassenreferenzen

Aus Appmethod Topics
Wechseln zu: Navigation, Suche

Nach oben zu Klassen und Objekte - Index

In manchen Situationen werden Operationen mit einer Klasse selbst und nicht mit ihren Instanzen (Objekten) durchgeführt. Dies geschieht beispielsweise, wenn Sie einen Konstruktor mit einer Klassenreferenz aufrufen. Sie können auf eine bestimmte Klasse immer über ihren Namen zugreifen. Manchmal müssen aber Variablen oder Parameter deklariert werden, die Klassen als Werte aufnehmen. Für diese Fälle benötigen Sie Klassenreferenztypen.

In diesem Thema werden folgende Bereiche erläutert:

  • Klassenreferenztypen
  • Klassen-Operatoren

Klassenreferenztypen

Klassenreferenztypen werden auch als Metaklassen bezeichnet. Die Definition erfolgt folgendermaßen:

class of Typ

Typ ist ein beliebiger Klassentyp. Der Bezeichner Typ gibt einen Wert des Typs class ofTyp an. Ist Typ1 ein Vorfahr von Typ2, dann ist class of Typ2 zuweisungskompatibel zu class of Typ1. Die Anweisung:

 type TClass = class of TObject;
 var AnyObj: TClass;

deklariert eine Variable namens AnyObj, die eine beliebige Klassenreferenz aufnehmen kann. Ein Klassenreferenztyp darf nicht direkt in einer Variablendeklaration oder Parameterliste definiert werden. Klassenreferenzvariablen kann auch der Wert nil zugewiesen werden.

Das folgende Beispiel (Konstruktor der Klasse Borland.VCL.Classes.TCollection in der Unit Classes) zeigt, wie Klassenreferenztypen verwendet werden:

 
 type TCollectionItemClass = class of TCollectionItem;
      ...
 constructor Create(ItemClass: TCollectionItemClass);

Diese Deklaration besagt, dass beim Erstellen eines Borland.VCL.Classes.TCollection-Instanzobjekts der Name einer von Borland.VCL.Classes.TCollectionItem abgeleiteten Klasse an den Konstruktor übergeben werden muss.

Klassenreferenztypen sind hilfreich, wenn Sie eine Klassenmethode oder einen virtuellen Konstruktor in einer Klasse oder einem Objekt aufrufen wollen, dessen aktueller Typ zur Compilierzeit nicht bekannt ist.

Konstruktoren und Klassenreferenzen

Ein Konstruktor kann mit einer Variablen eines Klassenreferenztyps aufgerufen werden. Auf diese Weise können Objekte erstellt werden, deren Typ zur Compilierzeit nicht bekannt ist. Beispiel:

 
 type TControlClass = class of TControl;
 
 function CreateControl(ControlClass: TControlClass;
     const ControlName: string; X, Y, W, H: Integer): TControl;
   begin
     Result := ControlClass.Create(MainForm);
     with Result do
      begin
        Parent := MainForm;
        Name := ControlName;
        SetBounds(X, Y, W, H);
        Visible := True;
      end;
   end;

Der Funktion CreateControl wird eine Klassenreferenz als Parameter übergeben. Er bestimmt, welche Art von Steuerelement erstellt wird. Der Parameter wird anschließend beim Aufruf des Konstruktors verwendet. Da Klassentypbezeichner Klassenreferenzwerte enthalten, kann im Aufruf von CreateControl der Bezeichner der Klasse angegeben werden, um eine Instanz vor ihr zu erstellen. Beispiel:

 CreateControl(TEdit, 'Edit1', 10, 10, 100, 20);

Konstruktoren, die mit Klassenreferenzen aufgerufen werden, sind normalerweise virtuell. Die entsprechende Implementierung wird anhand des beim Aufruf angegebenen Laufzeittyps aktiviert.

Klassen-Operatoren

Klassenmethoden arbeiten mit Klassenreferenzen. Jede Klasse erbt von Borland.Delphi.System.TObject die zwei Klassenmethoden ClassType and ClassParent. Diese Methoden geben eine Referenz auf die Klasse eines Objekts und seiner direkten Vorfahrklasse zurück. Beide Methoden geben einen Wert des Typs Borland.Delphi.System.TClass (TClass = class of TObject) zurück, der in einen spezielleren Typ umgewandelt werden kann. Alle Klassen erben außerdem die Methode InheritsFrom, mit der Sie ermitteln können, ob ein Objekt von einer bestimmten Klasse abgeleitet ist. Diese Methoden werden von den Operatoren is und as verwendet und normalerweise nicht direkt aufgerufen.

Der Operator is

Der Operator is führt eine dynamische Typprüfung durch. Mit ihm können Sie den aktuellen Laufzeittyp eines Objekts ermitteln. Der Ausdruck

ObjektisKlasse

gibt True zurück, wenn Objekt eine Instanz der angegebenen Klasse oder eines ihrer Nachkommen ist. Trifft dies nicht zu, wird False zurückgegeben (hat Objekt den Wert nil, ist der Rückgabewert ebenfalls False). Wenn der deklarierte Typ von Objekt nicht in Beziehung zu Klasse Klasse steht (wenn die Typen also unterschiedlich und nicht voneinander abgeleitet sind), gibt der Compiler eine Fehlermeldung aus. Beispiel:

 if ActiveControl is TEdit then TEdit(ActiveControl).SelectAll;

Diese Anweisung wandelt die ActiveControl-Variable in den TEdit-Typ um. Sie prüft zuerst, ob das von ActiveControl referenzierte Objekt eine Instanz von TEdit oder eine davon abgeleitete Klasse ist.

Der Operator as

Der Operator as führt eine Typumwandlung mit Laufzeitprüfung durch. Der Ausdruck

ObjektasKlasse

gibt eine Referenz auf dasselbe Objekt wie Objekt, aber mit dem von Klasse angegebenen Typ zurück. Zur Laufzeit muss Objekt eine Instanz von Klasse oder einem ihrer Nachkommen bzw. nil sein. Andernfalls wird eine Exception ausgelöst. Wenn der deklarierte Typ von Objekt nicht in Beziehung zu Klasse steht (wenn die Typen also unterschiedlich und nicht voneinander abgeleitet sind), gibt der Compiler eine Fehlermeldung aus. Beispiel:

 
 with Sender as TButton do
  begin
   Caption := '&Ok';
   OnClick := OkClick;
  end;

Die Regeln der Auswertungsreihenfolge machen es häufig erforderlich, as-Typumwandlungen in Klammern zu setzen. Beispiel:

 (Sender as TButton).Caption := '&Ok';

Siehe auch

Codebeispiele