gpt4 book ai didi

delphi - Delphi在编译时复制基类型未知的通用对象

转载 作者:行者123 更新时间:2023-12-03 18:35:30 25 4
gpt4 key购买 nike

我想复制通用对象,但是它的类型只能在运行时由“类的”构造获取,因为源对象的类型可能不同(TItem或TSpecificItem等):

type
TItem = class
//...
procedure Assign(Source: TItem);virtual; abstract; //edit
end;

TSpecificItem = class(TItem)
//...
end;

TEvenMoreSpecificItem = class(TSpecificItem)
//...
end;

TItemClass = class of TItem;

TItemContainer = class
FItems: TObjectList<TItem>; //edit
procedure Assign(Source: TObject); //edit
function GetItem(Index: Integer): TItem; inline; //edit
procedure SetItem(Index: Integer; Item: TItem); inline; //edit
function Count: Integer; //edit;
function ItemClass: TItemClass; virtual; abstract;
property Items[Index: Integer]: TItem read GetItem write SetItem; //edit
end;

TItemContainer<T: TItem> = class(TItemContainer)
//...
function GetItem(Index: Integer): T; inline; //edit
procedure SetItem(Index: Integer; Item: T); inline; //edit
function ItemClass: TItemClass; override;
property Items[Index: Integer]: T read GetItem write SetItem; default; //edit
end;

//start of edit
function TItemContainer.Count: Integer;
begin
Result := FItems.Count;
end;

function TItemContainer.GetItem(Index: Integer): TItem;
begin
Result := FItems[Index];
end;

procedure TItemContainer.SetItem(Index: Integer; Item: TItem);
begin
FItems[Index].Assign(Item);
end;

procedure TItemContainer.Assign(Source: TObject);
var
I: Integer;
Item: TItem;
Cls: TClass;
begin
if Source is TItemContainer then
begin
FItems.Clear;
for I := 0 to TItemContainer(Source).Count - 1 do
begin
Item := TItemContainer(Source).Items[I];
Cls := Item.ClassType;
Item := TItemClass(Cls).Create;
Item.Assign(TItemContainer(Source).Items[I]);
FItems.Add(Item);
end;
end;
end;

function TItemContainer<T>.GetItem(Index: Integer): T;
begin
Result := T(inherited GetItem(Index));
end;

procedure TItemContainer<T>.SetItem(Index: Integer; Item: T);
begin
inherited SetItem(Index, Item);
end;
//end of edit

function TItemContainer<T>.ItemClass: TItemClass;
begin
Result := TItemClass(GetTypeData(PTypeInfo(TypeInfo(T)))^.ClassType);
end;

function CopyGenericObject(Source: TItemContainer): TItemContainer;
var
Cls: TItemClass;
begin
Cls := Source.ItemClass;
Result := TItemContainer<Cls>.Create; // compiler reports error "incompatible types"
Result.Assign(Source);
end;

// edit:
procedure DoCopy;
var
Source: TItemContainer<TEvenMoreSpecificItem>;
Dest: TItemContainer;
begin
Source := TItemContainer<TEvenMoreSpecificItem>.Create; // for example
//add some items to Source
Dest := CopyGenericObject(Source);
//use the result somewhere
end;


我必须使用Delphi XE。

我发现了
http://docwiki.embarcadero.com/RADStudio/XE6/en/Overview_of_Generics


动态实例化

不支持在运行时进行动态实例化。


是我想做的吗?

最佳答案

如果我理解得很好,您正在寻找的是实现一个例程,该例程将创建与给定源具有相同类型的类的实例。可以这样做:

type
TItemContainerclass = class of TItemContainer;

function CopyGenericObject(Source: TItemContainer): TItemContainer;
begin
Result := TItemContainerclass(Source.ClassType).Create;
end;


另外,您可以将ItemClass例程简化为

function TItemContainer<T>.ItemClass: TItemClass;
begin
Result := T;
end;


请注意,这只会创建一个新实例,而不是源副本,但是由于您的代码未显示任何试图复制对象并仅创建新实例的尝试,因此我认为这是您的预期结果。

注意:这在Delphi 10中有效,我无权使用XE进行测试。

关于delphi - Delphi在编译时复制基类型未知的通用对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34510995/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com