![]() |
Delphi-Version: XE
generische Liste als Parameter, Vererbung
Hallo alle... :P
Ich habe mehrere generische Listen welche von einer "Basis" Liste abgeleitet sind.
Delphi-Quellcode:
Jetzt wollte ich ein Event bauen was bei einer Änderung egal welcher Liste gefeuert wird. Der Empfänger soll dann schauen um welche Liste es sich handelt und entsprechend weiterverarbeiten.
TListBasis<T: class> = class(TObjectList<T>)
public constructor Create; virtual; end; TList1 = TListBasis<TBlubb> TList2 = TListBasis<TBla>
Delphi-Quellcode:
...resultiert in:
TOnLoadListEvent = procedure (Sender: TObject; aList: TListBasis<T>) of object;
if Assigned(FOnLoadList) then begin FOnLoadList(Self, FList2); // FList2 = Instanz von TList2 end; Zitat:
Danke... |
AW: generische Liste als Parameter, Vererbung
Delphi-Quellcode:
!=
TListBasis<T: class>
Delphi-Quellcode:
was passiert wenn du das in ersteres änderst?
TListBasis<T>
|
AW: generische Liste als Parameter, Vererbung
Danke für die Rückmeldung. 8-)
Ich habe schon diverse Varianten durch. Diese auch. Ich suche schon den Vormittag nach meinem Denkfehler. Ich denke langsam, das das nicht möglich ist. |
AW: generische Liste als Parameter, Vererbung
habs:
Delphi-Quellcode:
Einsatzbeispiel:
TOnLoadListEvent<T> = procedure (Sender: TObject; aList: TListBasis<T>) of object;
Delphi-Quellcode:
-----------------------------------------------------------------------------------
private
FOnLoadList : TOnLoadListEvent<TBla>; { Private-Deklarationen } public property OnLoadList : TOnLoadListEvent<TBla> read FOnLoadList write FOnLoadList; Was nicht geht:
Delphi-Quellcode:
da gibt es einen Fehler:
private
FOnLoadList : TOnLoadListEvent<T>; { Private-Deklarationen } public property OnLoadList : TOnLoadListEvent<T> read FOnLoadList write FOnLoadList; [dcc32 Fehler] Unit2.pas(27): E2511 Typparameter 'T' muss ein Klassentyp sein |
AW: generische Liste als Parameter, Vererbung
Danke für deine Bemühungen... :P
Tja, da kann man dem Event aber nur TBla übergeben. Es sollte aber auch TBlubb gehen. Deshalb hatte ich das über den "Vorfahr" versucht. :( Alternative wäre für jeden Listentyp ein getrenntes Event. :( |
AW: generische Liste als Parameter, Vererbung
Klarer Fall von "hier fehlt uns die
![]() |
AW: generische Liste als Parameter, Vererbung
Ich verstehe nicht wo hier Kovarianz ins Spiel kommt. Wir leiten doch hier nirgendwo von
Delphi-Quellcode:
ab. Seine Motivation ist dass seine
TListBasis<T>
Delphi-Quellcode:
und
TList1
Delphi-Quellcode:
-Instanzen auch ein Event haben, dessen Parameter
TList2
Delphi-Quellcode:
bzw.
TBlubb
Delphi-Quellcode:
-Instanzen sind.
TBla
Und das ist doch so gegeben, oder?
Delphi-Quellcode:
TListBasis<T: class> = class(TObjectList<T>)
public type TOnLoadListEvent = TProc<TObject, TListBasis<T>>; public var OnLoadList: TOnLoadListEvent; end; TBlubb = class(TObject); TBla = class(TObject); TList1 = TListBasis<TBlubb>; TList2 = TListBasis<TBla>; |
AW: generische Liste als Parameter, Vererbung
Die Kovarianz kommt ins Spiel, sobald ich eine TList<derived> als TList<base> behandeln will um ebend nicht für jeden Typen in der Liste einen Speziellen Event Handler zu haben.
Warum? Weil dann jeder, der mal an dieses Event gehen möchte, einen Event handler für genau diesen Typ in der Liste implementieren muss. Und nebenbei bemerkt und leicht off topic ist es ![]() Allerdings fehlt atm noch die Information, warum der Event handler die Liste braucht. Was wird damit gemacht? Hier mal hingeschludert, wie über ein Interface (wie in meinem Blogpost erklärt) ein sicherer Lesezugriff auf eine generische Objectliste realisiert werden kann.
Delphi-Quellcode:
program Project1;
{$APPTYPE CONSOLE} uses Generics.Collections, SysUtils; type IReadOnlyObjectList = interface ['{3DFBDE4F-16A4-4395-AB29-58671BD7EC1E}'] function GetClassType: TClass; function GetCount: Integer; function GetItem(Index: Integer): TObject; function GetEnumerator: TEnumerator<TObject>; property ClassType: TClass read GetClassType; property Count: Integer read GetCount; property Items[Index: Integer]: TObject read GetItem; default; end; TListBasis<T: class> = class(TObjectList<T>, IReadOnlyObjectList) private function GetClassType: TClass; function GetCount: Integer; function GetItem(Index: Integer): TObject; function GetEnumerator: TEnumerator<TObject>; protected function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; public constructor Create; virtual; end; { TListBasis<T> } constructor TListBasis<T>.Create; begin inherited Create; end; function TListBasis<T>.GetClassType: TClass; begin Result := T; end; function TListBasis<T>.GetCount: Integer; begin Result := inherited Count; end; function TListBasis<T>.GetEnumerator: TEnumerator<TObject>; begin Result := TEnumerator<TObject>(inherited GetEnumerator); end; function TListBasis<T>.GetItem(Index: Integer): TObject; begin Result := TObject(inherited Items[Index]); end; function TListBasis<T>.QueryInterface(const IID: TGUID; out Obj): HRESULT; begin if GetInterface(IID, obj) then Result := S_OK else Result := E_NOINTERFACE; end; function TListBasis<T>._AddRef: Integer; begin Result := -1; end; function TListBasis<T>._Release: Integer; begin Result := -1; end; type TOnLoadListEvent = procedure (Sender: TObject; const aList: IReadOnlyObjectList) of object; TBla = class end; TTest = class private FOnLoadList: TOnLoadListEvent; FList: TListBasis<TBla>; procedure LoadListHandler(Sender: TObject; const aList: IReadOnlyObjectList); public constructor Create; destructor Destroy; override; procedure LoadStuff; end; { TTest } constructor TTest.Create; begin inherited Create; FList := TListBasis<TBla>.Create; FOnLoadList := LoadListHandler; end; destructor TTest.Destroy; begin FList.Free; inherited; end; procedure TTest.LoadListHandler(Sender: TObject; const aList: IReadOnlyObjectList); var obj: TObject; begin Writeln(aList.Count, ' items of type ', aList.ClassType.ClassName); end; procedure TTest.LoadStuff; begin FList.AddRange([TBla.Create, TBla.Create, TBla.Create, TBla.Create]); if Assigned(FOnLoadList) then FOnLoadList(Self, FList); end; var test: TTest; begin try test := TTest.Create; try test.LoadStuff; finally test.Free; end; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; Readln; end. |
AW: generische Liste als Parameter, Vererbung
Hallo alle...
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:47 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