我有一个从 TStringList 对象派生的对象,我称之为“TAutoString”。它允许您在创建列表时指定对象类型。然后,每次将新条目添加到字符串列表时,它还会创建与该字符串条目关联的对象的副本。这使得与每个字符串一起存储各种附加信息变得很容易。例如:
type TMyObject = class(TObject)
public
Cats: integer;
Dogs: integer;
Mice: integer;
end;
MO := TAutoString.Create(TMyObject);
在对象内部,类信息存储在类变量中:
private
ObjectClass: TClass;
constructor TAutoString.Create(ObjClass: TClass);
begin
inherited Create;
ObjectClass:=ObjClass;
end;
现在,每次添加新项目时,它都会创建一个指定类型的新对象:
function TAutoString.Add(const S: string): Integer;
begin
Result:=inherited Add(S);
Objects[Result]:=ObjectClass.Create;
end;
我现在可以添加或读取与每个字符串条目相关的信息。
TMyObject(MO.Objects[25]).Cats := 17;
D:=TMyObject(MO.Objects[25]).Dogs;
当对象没有构造函数时,这很有效。如果对象有构造函数,则在创建对象时不会调用其构造函数,因为 TObject 的构造函数不是虚拟的。
谁能想到解决这个问题的方法。我见过使用 RTTI 库的解决方案,但这是在 Delphi-7 中,它没有 RTTI 库。
顺便说一句,TObject 的构造函数不是虚拟的似乎有点奇怪。如果是这样,它将启用各种有用的功能,例如我正在尝试实现的功能。
编辑:雷米的建议只是我需要的轻推。我最初尝试过类似的策略,但我无法让它发挥作用。当它看起来不像我认为的那样工作时,我认为一定有一些我不了解虚拟方法的地方。他的帖子促使我再看一遍。事实证明,我已经为要附加的对象的构造函数放弃了“覆盖”指令。现在它按应有的方式工作。
我担心的另一个问题是我已经在一堆其他应用程序中使用了自动字符串,其中对象基于“TObject”,我不想回去更改所有代码。我通过重载构造函数并为基于 TObject 的对象和另一个用于我的 TAutoClass 对象的构造函数解决了这个问题:
constructor Create(ObjClass: TAutoClass); overload; virtual;
constructor Create(ObjClass: TClass); overload; virtual;
根据调用哪个构造函数,对象类存储在不同的变量中。
private
AutoClass: TAutoClass;
ObjectClass: TClass;
然后,当构建对象时,我会检查已分配的对象并使用该对象:
procedure TAutoString.CreateClassInstance(Index: integer);
begin
if AutoClass<>nil then Objects[Index]:=AutoClass.Create
else Objects[Index]:=ObjectClass.Create
end;
新版本完美地适用于任何一种类型的对象。