![]() |
Delphi-Version: XE2
Eine Generics TObjectList<T> als Parameter
Hallo zusammen,
ich habe eine generics ObjectList so definiert
Delphi-Quellcode:
und als Variable so definiert
TCustomObjectList<T: class> = class(TObjectList<T>)
Delphi-Quellcode:
. Das funktioniert auch wunderbar. Ich kann ja die Generic-ObjectList so wie ich Sie als Variable deklariert habe übergeben :
ZahlungsartList : TCustomObjectList<TZahlungsart>;
Delphi-Quellcode:
. Wie kann ich auch das <TZahlungsart> als Parameter definieren in dem Procedure-Kopf ?
procedure foobar(liste: CustomObjectList<TZahlungsart>);
|
AW: Eine Generics TObjectList<T> als Parameter
Delphi-Quellcode:
Meinst Du sowas?
type
TFoo = class procedure bar<T>(meineList:Tobjectlist<T>); end; |
AW: Eine Generics TObjectList<T> als Parameter
Nein, ich möchte in einer externen eigenständigen Funktion auf Werte von den Generics-ObjectListen zugreifen. In dieser Funktion soll dann anhand der übergebenen Liste entschieden werden, was gemacht werden soll.
Der Pseudocode soll zeigen, was ich machen möchte :
Delphi-Quellcode:
Der Aufruf aus der Form soll dann zum Beispiel so aussehen :
interface
type TZahlungsart = class private {...} public {...} end; TPostleitzahlen = class private {...} public {...} end; TCustomObjectList<T: class> = class(TObjectList<T>) private {...} public {...} end; var ZahlungsartList : TCustomObjectList<TZahlungsart>; Postleitzahlen : TCustomObjectList<TPostleitzahlen>; implementation procedure Test(ObjectList: ??????); var tmpName : string; begin tmpName := ObjectList.Items[Counter].<Feld>; end:
Delphi-Quellcode:
Statt Zahlungsart kann da auch Postleitzahlen stehen.
procedure TForm1.Button1Click(Sender: TObject);
begin procedure Test(ZahlungsartList); end; |
AW: Eine Generics TObjectList<T> als Parameter
Als globale Prozedur wird das nicht gehen, lediglich als Methode eines Records oder einer Klasse:
Delphi-Quellcode:
TDummy = record
class procedure Test<T:class>(ObjectList: TCustomObjectList<T>); static; end; TDummy.Test<TZahlungsart>(ZahlungsartList); TDummy.Test<TPostleitzahlen>(Postleitzahlen); |
AW: Eine Generics TObjectList<T> als Parameter
oder so, wem das besser gefällt (kommt aber, von der Verwendung her, auf's Selbe raus ... ich find Record auch schöner, aber Klasse ist ableitbar/erweiterbar)
Delphi-Quellcode:
TDummy = class abstract // ältere Delphis: wenn's nicht geht, dann abstract einfach weglassen
class procedure Test<T:class>(ObjectList: TCustomObjectList<T>); static; end; Schade das emba nicht auf mich hört und bei generischen Funktionen einfach eine DummyKlasse/Record drumzupacken, wenn die es nicht schaffen es ihrem Compiler beizubringen, dßa es generische Funktion gibt. |
AW: Eine Generics TObjectList<T> als Parameter
Hm, das ist nicht ganz das was ich wollte. Aber ok, dann muss ich ein bisschen umkoordinieren.
|
AW: Eine Generics TObjectList<T> als Parameter
Da wir einen Typconstraint auf class haben, können wir davon ausgehen dass jedes T eine Klasse ist.
Somit können wir auch gefahrlos einen Hardcast auf TCustomObjectList<TObject> machen (Stichwort: Kovarianz). Bei der Instanzierung einer Liste, merken wir uns, von welchem Typ T ist. Dies muss auf Instanzebene gespeichert werden, damit wir auch nach dem zuvor erwähnten Hardcast noch die richtige Klasse herausbekommen.
Delphi-Quellcode:
type
TCustomObjectList<T: class> = class(TObjectList<T>) private FItemClass: TClass; public constructor Create(AOwnsObjects: Boolean = True); overload; function AsNonGeneric: TCustomObjectList<TObject>; property ItemClass: TClass read FItemClass; end; TCustomObjectList = TCustomObjectList<TObject>; function TCustomObjectList<T>.AsNonGeneric: TCustomObjectList<TObject>; begin Result := TCustomObjectList<TObject>(Self); end; constructor TCustomObjectList<T>.Create(AOwnsObjects: Boolean); begin inherited Create(AOwnsObjects); FItemClass := T; end; procedure Test(ObjectList: TCustomObjectList); begin Writeln(objectList.ItemClass.ClassName); end; var ZahlungsartList: TCustomObjectList<TZahlungsart>; Postleitzahlen: TCustomObjectList<TPostleitzahlen>; begin ZahlungsartList := TCustomObjectList<TZahlungsart>.Create; Postleitzahlen := TCustomObjectList<TPostleitzahlen>.Create; Test(ZahlungsartList.AsNonGeneric); Test(Postleitzahlen.AsNonGeneric); end. |
AW: Eine Generics TObjectList<T> als Parameter
Zitat:
|
AW: Eine Generics TObjectList<T> als Parameter
Was willst du denn überladen?
Aber ja, "overload" funktioniert wie mit jeder normalen Methode auch. PS: Man kann sich auch aussuchen wo man den generischen Typen deklariert.
Delphi-Quellcode:
Letzeres hat einen Vorteil, wenn man eine Funktion mit einem bestimmten Typen oft aufruft.
TDummy = record // oder class macht keinen großen Unterschied
class procedure Test<T:class>(ObjectList: TCustomObjectList<T>); static; end; TDummy.Test<TZahlungsart>(ZahlungsartList); TDummy.Test<TPostleitzahlen>(Postleitzahlen); TDummy<T:class> = record // oder class macht keinen großen Unterschied class procedure Test(ObjectList: TCustomObjectList<T>); static; end; TDummy<TZahlungsart>.Test(ZahlungsartList); TDummy<TPostleitzahlen>.Test(Postleitzahlen); Ersteres, wenn man viele Verschiedene Typen nutzt. Und es läßt sich beliebig kombinieren.
Delphi-Quellcode:
type ZahlDummy = TDummy<TZahlungsart>;
ZahlDummy.Test(ZahlungsartList); |
AW: Eine Generics TObjectList<T> als Parameter
Zitat:
Delphi-Quellcode:
So wie ich es im Beispiel angegeben habe, funktioniert es nicht mit static oder overload. Dieses soll nur ein Beispiel sein um das Überladen zu verstehen.
TDummy = record
class procedure Test<T:class>(ObjectList: TCustomObjectList<T>; ID: Integer); static; class procedure Test<T:class>(ObjectList: TCustomObjectList<T>; ID: string); static; end; TDummy.Test<TZahlungsart>(ZahlungsartList, 1); TDummy.Test<TZahlungsart>(ZahlungsartList, '1'); |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:24 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