基于早期的post,我编写了以下代码。请原谅这篇文章的详细内容。我相信所有各方都可以使用完整的代码进行测试和评论。
program sandbox;
{$APPTYPE CONSOLE}
uses
SysUtils,
Generics.Collections;
type
TDataType = class
// Stuff common to TInt and TStr
end;
TInt = class(TDataType)
FValue: integer;
constructor Create(Value, Low, High: integer);
end;
TStr = class(TDataType)
FValue: string;
constructor Create(Value: string; Length: integer);
end;
TSomeClass = class
FIntList: TList<TInt>;
FStrList: TList<TStr>;
procedure AddToList<T: TDataType>(Element: T);
constructor Create();
procedure Free();
end;
constructor TInt.Create(Value, Low, High: Integer);
begin
inherited Create();
FValue := Value;
end;
constructor TStr.Create(Value: string; Length: Integer);
begin
inherited Create();
FValue := Value;
end;
procedure TSomeClass.AddToList<T>(Element: T);
begin
if TObject(Element) is TInt then
FIntList.Add(Element)
else if TObject(Element) is TStr then
FStrList.Add(Element);
end;
constructor TSomeClass.Create();
begin
inherited;
FIntList := TList<TInt>.Create();
FStrList := TList<TStr>.Create();
end;
procedure TSomeClass.Free();
var
SomeIntItem: TInt;
SomeStrItem: TStr;
begin
for SomeIntItem in FIntList do begin
SomeIntItem.Free();
end;
for SomeStrItem in FStrList do begin
SomeStrItem.Free;
end;
FIntList.Free();
FStrList.Free();
end;
var
Inst: TSomeClass;
begin
try
{ TODO -oUser -cConsole Main : Insert code here }
Inst := TSomeClass.Create;
Inst.AddToList(TInt.Create(100, 0, 101));
Inst.AddToList(TStr.Create('Test', 10));
Inst.Free;
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
end.
请注意,现实世界中TInt
和TStr
的构造函数也会使用Low, High: integer
和Length: integer
参数。我在if TObject(Element) is TInt then
和else if TObject(Element) is TStr then
运行Delphi 2009时遇到了“E2089无效的类型转换”。有谁知道为什么会这样?
修改:请注意,TInt
和TStr
只是其他10到20种类型中的两种;否则重载是该作业的工具。 :)
答案 0 :(得分:7)
重新考虑你的设计。您可以使用重载而不是泛型类型参数,如下所示:
procedure Add (SomeString : TString); overload;
procedure Add (SomeInt : TInt); overload;
或者,如果你想使用多态,请执行Gamecat建议的操作,并将基类型作为参数传递,在该参数上使用is
:
procedure Add (Element : TDataType);
Rob在对你上一个问题的评论中指出:如果你只允许两种类型并且根据实际类型有条件,那么它并不是通用的。因此,泛型可能是错误的工具。
希望有所帮助。
答案 1 :(得分:3)
问题不在于泛型。您将TDataType添加到需要TInt或TStr的列表中:
procedure TSomeClass.AddToList<T>(Element: T);
begin
if TObject(Element) is TInt then
FIntList.Add(TInt(Element))
else if TObject(Element) is TStr then
FStrList.Add(TStr(Element));
end;
解决问题。
但为什么不使用:
procedure TSomeClass.AddToList(Element: TDataType);
begin
if Element is TInt then
FIntList.Add(TInt(Element))
else if Element is TStr then
FStrList.Add(TStr(Element));
end;