Klassenreferenzen
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
Inhaltsverzeichnis
Klassenreferenztypen
Klassenreferenztypen werden auch als Metaklassen bezeichnet. Die Definition erfolgt folgendermaßen:
class of type
Typ ist ein beliebiger Klassentyp. Der Bezeichner Typ gibt einen Wert des Typs class of Typ an. Ist Typ1 ein Vorfahre 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 System.Classes.TCollection in der Unit System.Classes) zeigt, wie Klassenreferenztypen verwendet werden:
type TCollectionItemClass = class of TCollectionItem;
...
TCollection = class(TPersistent)
...
constructor Create(ItemClass: TCollectionItemClass);
Diese Deklaration besagt, dass beim Erstellen eines TCollection-Instanzobjekts der Name einer von 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 TObject die zwei Klassenmethoden ClassType und ClassParent. Diese Methoden geben eine Referenz auf die Klasse eines Objekts und seiner direkten Vorfahrklasse zurück. Beide Methoden geben einen Wert des Typs 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
Objekt is Klasse
gibt True zurück, wenn Objekt eine Instanz der von 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 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
Objekt as Klasse
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
- Klassen und Objekte
- Felder
- Methoden
- Eigenschaften
- Verschachtelte Typdeklarationen
- Exceptions
- Überladene Operatoren (Delphi)
- Unterstützende Klassen und Records (Delphi)