Mittwoch, 23. Mai 2012


Artikel

September 2008 | Artikel

Delphi 2009 Fortsetzung, Teil 3

Teil 1   Teil 2   Teil 3   Teil 4   

Generics

von Holger Flick

„Generics“ (oder „Generische Typen“) sind eine Spracherweiterung von Delphi, die bisher der Delphi .NET Seite vorenthalten war. Java und C# können ebenfalls schon seit längerem mit generischen Typ- bzw. Klassenkonstrukten glänzen. Selbst C++ ermöglicht die Implementierung von generischen Klassen schon immer über sog. Templates. Somit ist neben dem erhöhten Nutzen dieses Hilfsmittel im Quellcode einzusetzen, die Entscheidung geradezu nur konsequent von CodeGear, dieses Feature für Delphi 2009 auch in den nativen Windows Compiler zu übernehmen. Diese Erweiterung ist zudem in jeder Edition von Delphi enthalten, sodass keine zusätzlichen Kosten entstehen, wenn man Generics einsetzt. Einziger Wermutstropfen bei dem Einsatz von Generics ist, dass Quellcode, der dieses Sprachkonstrukt verwendet, nur noch ab Delphi 2009 und aufwärts kompiliert werden kann.

Ich werde eine kurze Einführung zur Verwendung von Generics geben, die unmittelbar aufzeigen wird, wo entscheidende Vorteile für den Entwickler durch den Einsatz von ihnen liegen. Es bleibt hervorzuheben, dass Generics nur direkte Vorzüge für den Entwickler haben, nur indirekt wirkt es sich auf das endgültige Softwareprodukt aus, da Programmierfehler bereits zur Zeit der Kompilierung aufgedeckt werden können, die vorher erst zur Laufzeit durch eine Exception aufgefallen sind.

Mit Delphi 2009 wurde neben der Erweiterung des Komponentenangebotes die VCL mit generischen Containerklassen erweitert. Im Wesentlichen gibt es nun für alle Klassen in Contnrs.pas generische Pendants. Wir werden hier beispielhaft TObjectList verwenden.

Es soll folgende Klassenstruktur betrachtet werden. Es gibt zwei Oberklassen: TAnimal und THuman. Von TAnimal werden zwei weitere Klassen abgeleitet TDog und TCat. TAnimal besitzt eine Eigenschaft mit dem Namen des Tieres. Der Name wird in meinem Beispiel automatisch mit einem eindeutigen Wert bei Instanziierung eines Objektes belegt. Zudem sei eine Methode namens Log definiert, die den Namen für den Benutzer ausgibt. Es ergibt sich die folgende Klassendefinition in Object Pascal:

  1. type
  2. TAnimal = class
  3. private
  4. FName: String;
  5. public
  6. procedure Log;
  7. property Name:string read FName write FName;
  8. // ...
  9. end;
  10. TDog = class(TAnimal)
  11. end;
  12. TCat = class(TAnimal)
  13. end;
  14. THuman = class
  15. end;

Bis Delphi 2007 konnten wir mehrere Objekte des Types TAnimal wie folgt in einer TObjectList ablegen:

  1. var
  2. oldAnimals: TObjectList;
  3. anAnimal: TAnimal;
  4. begin
  5. oldAnimals := TObjectList.Create(true); oldAnimals.Add( TAnimal.Create );

Die Objekte konnten wir dann wie folgt von der Liste auslesen und den Namen ausgeben:

  1. for i := 0 to oldAnimals.Count-1 do
  2. begin
  3. anAnimal := oldAnimals[i] as TAnimal;
  4. anAnimal.Log;
  5. end;

Dieser Ansatz funktioniert auch noch, wenn wir Objekte von Klassen auf der Liste ablegen, die von TAnimal abgeleitet sind:

  1. oldAnimals := TObjectList.Create(true);
  2. oldAnimals.Add( TAnimal.Create );
  3. oldAnimals.Add( TCat.Create );
  4. oldAnimals.Add( TDog.Create );

Was passiert aber nun, wenn wir folgendes Konstrukt kompilieren:

  1. oldAnimals := TObjectList.Create(true);
  2. oldAnimals.Add( TAnimal.Create );
  3. oldAnimals.Add( THuman.Create );

Es sei daran erinnert, dass THuman nicht von TAnimal abstammt. Somit wirft der Typecast von THuman auf TAnimal zur Laufzeit eine Exception. Was bemerkt der Entwickler von dieser Exception? Der Compiler hat leider keine Möglichkeit, diesen Programmierfehler zu erkennen. Eine TObjectList ist gerade so definiert, dass alle beliebigen Objekte, d.h. alles was von TObject abgeleitet ist, auf der Liste abgelegt werden dürfen. Dummerweise sind alle Objekte, die man mit Delphi instanziieren kann von TObject abgeleitet. Als Alternative blieb bisher nur mit viel Aufwand für jede einzelne Klasse eine eigene typsichere Kontainerklasse zu entwickeln – was typischerweise zu den üblichen, wenig befriedigenden Copy-and-Paste-Orgien geführt hat …

Teil 1   Teil 2   Teil 3   Teil 4   

Kommentare