Übersicht über Generics
Delphi unterstützt die Verwendung von Generics.
Inhaltsverzeichnis |
Wie Generics arbeiten
Die Begriffe Generics oder generische Typen beschreiben eine Reihe von Dingen, die in einer Plattform nach Typ parametrisiert werden können. Generics können sich auf generische Typen und generische Methoden, d.h. generische Prozeduren und generische Funktionen, beziehen.
Generics sind eine Menge von Abstraktions-Tools, die eine Trennung eines Algorithmus (Prozedur, Funktion) oder einer Datenstruktur (Klasse, Interface, Record) von einem oder mehreren konkreten Typen zulassen, die der Algorithmus oder die Datenstruktur verwendet.
Eine Methode oder ein Datentyp, der andere Typen in seiner Definition verwendet, kann allgemeiner gehalten werden, wenn ein oder mehrere konkrete Typen durch Typparameter ersetzt werden. Diese Typparameter werden dann einer Typparameterliste in der Deklaration der Methode oder Datenstruktur hinzugefügt. Dies ist vergleichbar mit dem Verallgemeinern einer Prozedur, wobei Instanzen einer literalen Konstante in deren Rumpf durch einen Parameternamen ersetzt werden, und der Parameter der Parameterliste der Prozedur hinzugefügt wird.
Zum Beispiel: Eine Klasse (TMyList), die eine Liste von Objekten (des Typs TObject) verwaltet, kann wiederverwendbarer und typsicher gemacht werden, indem die Vorkommen von TObject durch einen Typparameternamen (z.B. 'T') ersetzt werden, und der Typparameter der Typparameterliste der Klasse hinzugefügt wird, so dass daraus TMyList<T> wird.
Konkrete Verwendungen (Instantiierungen) eines generischen Typs oder einer generischen Methode können festgelegt werden, indem für den generischen Typ oder die generische Methode Typargumente bereitgestellt werden. Die Bereitstellung von Typargumenten konstruiert einen neuen Typ oder eine neue Methode, indem Instanzen des Typparameters in der generischen Definition durch das entsprechende Typargument ersetzt werden.
Beispielsweise könnte die Liste als TMyList<Double> verwendet werden. Dadurch wird der neue Typ TMyList<Double> erstellt, dessen Definition mit TMyList<T> identisch ist, außer dass alle Instanzen von 'T' in der Definition durch 'Double' ersetzt werden.
Generics (als Abstraktionsmechanismus) verdoppeln einen Großteil der Funktionalität des Polymorphismus, aber mit unterschiedlichen Merkmalen. Da ein neuer Typ oder eine neue Methode bei der Instantiierung konstruiert wird, können Typfehler schneller gefunden werden, nämlich bereits beim Compilieren und nicht erst bei der Ausführung. Dadurch wird auch der Optimierungsbereich vergrößert, aber mit einem Nachteil: Jede Instantiierung erhöht die Speicherauslastung der Anwendung, mit dem möglichen Ergebnis einer geringeren Ausführungsgeschwindigkeit.
Quelltextbeispiele
TSIPair ist eine Klasse, die zwei Datentypen enthält, String und Integer:
type
TSIPair = class
private
FKey: String;
FValue: Integer;
public
function GetKey: String;
procedure SetKey(Key: String);
function GetValue: Integer;
procedure SetValue(Value: Integer);
property Key: TKey read GetKey write SetKey;
property Value: TValue read GetValue write SetValue;
end;
Damit eine Klasse unabhängig vom Datentyp ist, ersetzen Sie den Datentyp durch einen Typparameter.
type
TPair<TKey,TValue>= class // deklariert den Typ TPair mit zwei Typparametern
private
FKey: TKey;
FValue: TValue;
public
function GetKey: TKey;
procedure SetKey(Key: TKey);
function GetValue: TValue;
procedure SetValue(Value: TValue);
property Key: TKey read GetKey write SetKey;
property Value: TValue read GetValue write SetValue;
end;
type
TSIPair = TPair<String,Integer>; // deklariert einen instantiierten Typ
TSSPair = TPair<String,String>; // deklariert mit anderen Datentypen
TISPair = TPair<Integer,String>;
TIIPair = TPair<Integer,Integer>;
TSXPair = TPair<String,TXMLNode>;
Plattformanforderungen und Unterschiede
Parametrisierte Typen werden vom Delphi für Win32-Compiler unterstützt.
Laufzeittypidentifikation (RTTI)
In Win32 verfügen parametrisierte Typen und Methoden über keine RTTI, instantiierte Typen dagegen schon. Ein instantiierter Typ ist die Kombination eines parametrisierten Typs mit einer Menge von Parametern.
Interface-GUID
In Win32 haben instantiierte Interface-Typen keine Interface-GUID.
Parametrisierte Methoden in Interfaces
Eine parametrisierte Methode (Methode, die mit Typparametern deklariert ist) kann nicht in einem Interface deklariert werden.
Zeitpunkt der Instantiierung
Parametrisierte Typen werden beim Compilieren instantiiert und in die ausführbaren und verschiebbaren Dateien ausgegeben. Instanzvariablen eines generischen Typs werden für Klassen zur Laufzeit und für generische Records beim Compilieren instantiiert.
Dynamische Instantiierung
Es wird keine dynamische Instantiierung zur Laufzeit unterstützt.
Interface-Einschränkungen
Das Win32-Interface ist kein "leichtes" Interface. Das bedeutet, dass alle Typparameter mit Interface-Einschränkungen immer die COM IUnknown-Methoden _AddRef, _Release und QueryInterface unterstützen oder von TInterfacedObject erben. Record-Typen können keinen Interface-Einschränkungsparameter festlegen.