![]() |
Generische Ableitung TList<>
Liste der Anhänge anzeigen (Anzahl: 1)
Toll die Spracherweiterung für generische Typen in D2009!
Nur, bei meiner ersten Anwendung einer TList<> Ableitung habe ich leider erste Schwierigkeiten. Denn ich möchte eine neue TList<> Ableitung erstellen, welche auf einer eignen Elementen-Klasse basiert, die nur ein ID-Property enthält, um später in der neuen List-Klasse nach dieser ID zu suchen:
Delphi-Quellcode:
In der neuen Liste möchte ich abgeleitete Klassen von TMyBase
TMyBase = class
strict private fID: string; public constructor Create(ID: string); property ID: string read fID; end; constructor TMyBase.Create(ID: string); begin fID := ID; end; ablegen und mit einer neuen Methode FindByID wieder finden.
Delphi-Quellcode:
Dies läuft so weit, nur scheint mir die nötige Typenkonvertierung
TMyList<T> = class(TList<TMyBase>)
public function FindByID(ID: string): TMyBase; end; function TMyList<T>.FindByID(ID: string): TMyBase; var c: integer; begin result := nil; for c := 0 to Count - 1 do if (Items[c] as TMyBase).ID = ID then result := Items[c]; end; Items[c] as TMyBase fraglich. Wenn ich jetzt eine Ableitung von TMyBase mache, sind in der Anwendung weitere Konvertierungen nötig:
Delphi-Quellcode:
Die Anwendung:
TMyName = class(TMyBase)
strict private fName: string; public constructor Create(ID, aName: string); property Name: string read fName; end; constructor TMyName.Create(ID, aName: string); begin inherited Create(ID); fName := aName; end;
Delphi-Quellcode:
Auch hier sollte meines erachtens die Typenonvertierung
UseMyList := TMyList<TMyName>.Create;
UseMyList.Add(TMyName.Create('ID-1', 'Meier')); UseMyList.Add(TMyName.Create('ID-2', 'Müller')); UseMyList.Add(TMyName.Create('ID-3', 'Tester')); MyString := (UseMyList.FindByID('ID-3') as TMyName).Name; (UseMyList.FindByID('ID-3') as TMyName) nicht mehr nötig sein, damit das generische Konzept richtig umgesetzt wird. Meine Vermutung ist, dass ich die FindByID Methode falsch deklariert habe, und dass der Rückgabe-Typ hier <T> sein müsste. Leider bekomme ich mit folgender Deklaration in D2009 neue Probleme, weil TMyBase nicht von T abgeleitet ist (und ich auch keinen Weg fand, dies zu tun).
Delphi-Quellcode:
Bei einer echten Anwendung mit Duzenden von Ableitungen wird diese kleine
TMyList<T> = class(TList<TMyBase>)
public function FindByID(ID: string): T; end; Unschönheit schnell zur grösseren Fehlerquelle. Deshalb möchte ich meinen ersten Ansatz hinterfragen lassen. Beiliegend die kurze Konsolen-Applikation zum Experimentieren, damit meine Abhandlung nicht reine Theorie bleibt. Danke für eure Lösungen. Gruss Christoph BTW: Refactoring von Klassennamen welche als Generische Typen verwendet werden (hier TMyBase) scheint in D2009 (noch) nicht zu funktionieren. Gibt es einen Workaround? |
Re: Generische Ableitung TList<>
Unterstützt Delphi keine generic constraints? Das wäre tödlich.. :?
Delphi-Quellcode:
TMyList<T: TMyBase> = class(TList<T>)
|
Re: Generische Ableitung TList<>
Liste der Anhänge anzeigen (Anzahl: 1)
Doch, genau das ist es! Damit lässt sicher das Problem lösen.
Jetzt habe ich nur noch ein weiteres Problem mit der Typenzuweisung result := nil:
Delphi-Quellcode:
Ich bin sicher, auch hierfür muss es eine Lösung geben!
TMyList<T: TMyBase> = class(TList<T>)
public function FindByID(ID: string): T; end; function TMyList<T>.FindByID(ID: string): T; var c: integer; begin // result := nil; -> DCC Error: E2010 Incompatible types: T and pointer for c := 0 to Count - 1 do if Items[c].ID = ID then result := Items[c]; end; Erstmal Besten Dank an Dax! |
Re: Generische Ableitung TList<>
Probier mal, ob es auch "T: class, TMyBase" oder etwas ähnliches annimmt - ansonsten dringend in die Sprachbeschreibung schauen ;) Mit den Delphi-Generics kenne ich mich nun leider garnicht aus, dass constraints so notiert werden wie oben hab' ich auch nur aus einem Blog aufgeschnappt.
|
Re: Generische Ableitung TList<>
OT:
Nach dem ersten 30 Sekunden langen Blick scheint mir die Delphi Implementation von Generics unnötig kompliziert. So der erste Eindruck. OnToppic: Probiere es mit :
Delphi-Quellcode:
Result := TObject(nil);
|
Re: Generische Ableitung TList<>
Zitat:
|
Re: Generische Ableitung TList<>
Leider erlaubt dies der Compiler nicht:
result := TObject(nil); -> E2010: Incompatible Types T and TObject Die Situation verändert sich auch nicht, wenn ich die veraltete Deklaration der Basis-Klasse anwende: TMyBase = class(TObject) Natürlich läuft auch der naheliegende Typcast nicht result := T(nil); -> E2089: Invalid Typcast Auch der Versuch mit der neuen Exit-Clause, die einen Rückgabe-Parameter erlaubt geht nicht: exit(nil); -> E2010: Incompatible Types T and Pointer Ich bin ratlos, kann mir aber nicht vorstellen, dass dieses Triviale Konstrukt nicht lösbar sein sollte. |
Re: Generische Ableitung TList<>
Zitat:
|
Re: Generische Ableitung TList<>
Liste der Anhänge anzeigen (Anzahl: 1)
Super, damit lässt sich auch das letzte Problem elegant lösen!
Gerne bilde ich die korrigierte Klasse TMyList nochmals vollständig ab. Im Anhang lege gleich noch das ganze Konsolen-Projekt bei.
Delphi-Quellcode:
Danke an alle für die Tatkräftige Unterstützung!
type
TMyList<T: TMyBase> = class(TList<T>) public function FindByID(ID: string): T; end; function TMyList<T>.FindByID(ID: string): T; var c: integer; begin result := Default(T); for c := 0 to Count - 1 do if Items[c].ID = ID then result := Items[c]; end; Das Help von D2009 ist im Vergleich zu D2005-D2007 spürbar besser. Leider enthalten die Kapitel Overview of Generics und folgende aber keine Hinweise zu dieser neuen Funktion Default. Auch sonst finde ich keinen passenden Hinweis. Im Kapitel Generic-Contraints sind alle Beispiele mit Interface Klassen geführt, weswegen ich nicht gleich auf die TMyList<T: TMyBase> kam. Kennt Ihr eine gute Einführung in Generics von Delphi auf dem Netz? |
Re: Generische Ableitung TList<>
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:12 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz