我试图为通用列表定义自己的项类型。所有项目都需要owner
属性。
type
TGenericCollection<TGenericCollectionItem: class> = class(TObjectList<TGenericCollectionItem>)
protected
procedure Notify(const Value: TGenericCollectionItem; Action: TCollectionNotification); override;
public
procedure Assign(Source: TGenericCollection<TGenericCollectionItem>); virtual;
end;
TGenericCollectionItem = class
private
FOwner: TGenericCollection<TGenericCollectionItem>; //another class can change this value if it was declared in the same unit
protected
function GetOwner: TGenericCollection<TGenericCollectionItem>; virtual;
public
constructor Create; virtual;
property Owner: TGenericCollection<TGenericCollectionItem> read GetOwner;
end;
implementation
{ TGenericCollection<TGenericCollectionItem> }
procedure TGenericCollection<TGenericCollectionItem>.Assign(
Source: TGenericCollection<TGenericCollectionItem>);
begin
AddRange(Source.ToArray);
end;
procedure TGenericCollection<TGenericCollectionItem>.Notify(
const Value: TGenericCollectionItem; Action: TCollectionNotification);
begin
inherited;
if (Action = cnAdded) then
begin
OutputDebugString(PChar(Value.ClassName)); // Debug Output: THandingItem Process GenericCollection.exe (2424)
OutputDebugString(PChar(Self.ClassName)); // Debug Output: THandingList Process GenericCollection.exe (2424)
// Value.FOwner := Self; // Error: [dcc32 Error] Unit2.pas(46): E2003 Undeclared identifier: 'FOwner'
// (Value as TGenericCollectionItem).FOwner := Self; // Error: [dcc32 Error] Unit2.pas(46): E2003 Undeclared identifier: 'FOwner'
// (Value as TGenericCollectionItem<T>).FOwner := Self; // Undeclared identifier 'T'
end;
end;
当我尝试更改FOwner
值时,编译器会说FOwner
是未声明的标识符。 THandingList
继承自TGenericCollection
。 THandingItem
继承自TGenericCollectionItem
。
我做错了什么? Sample project
UPD:TGenericCollectionItem
代码示例已更改。
控制台应用:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
System.Generics.Collections;
type
TGenericCollection<TGenericCollectionItem: class> = class(TObjectList<TGenericCollectionItem>)
protected
procedure Notify(const Value: TGenericCollectionItem; Action: TCollectionNotification); override;
end;
TGenericCollectionItem = class
public
Owner: TGenericCollection<TGenericCollectionItem>;
end;
procedure TGenericCollection<TGenericCollectionItem>.Notify(
const Value: TGenericCollectionItem; Action: TCollectionNotification);
begin
inherited;
if (Action = cnAdded) then
Value.Owner := Self;
end;
var
GenericCollectionItem: TGenericCollectionItem;
GenericCollection: TGenericCollection<TGenericCollectionItem>;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
GenericCollection := TGenericCollection<TGenericCollectionItem>.Create;
try
GenericCollectionItem := TGenericCollectionItem.Create;
GenericCollection.Add(GenericCollectionItem);
finally
GenericCollection.Free;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
答案 0 :(得分:1)
哦,这令人困惑。您已将TGenericCollectionItem
用作通用参数名称和类型名称。在TGenericCollection
代码中,名称TGenericCollectionItem
引用泛型类型参数,而不是同名的类。关于TGenericCollectionItem
泛型参数的所有知识都是它是一个类。也就是说,它来自TObject
。因此没有名为Owner
或FOwner
的成员。
更改
TGenericCollection<TGenericCollectionItem: class>
到
TGenericCollection<T: TGenericCollectionItem>
请注意,您可能需要转发声明TGenericCollectionItem
。
更新: Argh,由于Delphi泛型的设计缺陷,当其中一个相互引用的类是通用的时,前向声明将不起作用。见How to set a forward declaration with generic types under Delphi 2010?