Dav*_*vid 5 delphi oop inheritance
好吧,所以我有一个我们称之为的基类TFruit
.从这里有各种各样的后代TApple
,TOrange
等等.我需要将后代类的属性保存到文件中.
为了能够在加载数据时创建正确的类,每个类都需要ID
在写入实际数据之前写入文件.目前,我已经提出了以下方法:
type
TFruit = class
const ID = 0;
end;
TApple = class(TFruit)
const ID = 1;
end;
TOrange = class(TFruit)
const ID = 2;
end;
Run Code Online (Sandbox Code Playgroud)
测试这个,我发现我需要非常小心我宣布哪个类.如果我用这个:
var Fruit: TFruit;
Fruit := TOrange.Create;
Run Code Online (Sandbox Code Playgroud)
...然后Fruit.ID
将返回零.然而,声明Fruit
作为一个TOrange
意志会产生预期的结果Fruit.ID = 2
(任何人都知道为什么?)
所以基本上,我这样做是对还是有更好的方法呢?通过比较(额外的函数声明,实现和代码),必须创建一个类函数并从那里返回一个值似乎非常难看.
更容易维护的解决方案是创建一个映射类,您可以在其中注册要转换为整数的所有类.
好处
用法
RegisterClass.Register(0, TFruit);
RegisterClass.Register(1, TApple);
RegisterClass.Register(2, TOrange);
Run Code Online (Sandbox Code Playgroud)
履行
TRegisterClass = class
private
FList: TStringList;
public
function FindID(AClass: TClass): Integer;
function FindClassName(const ID: Integer): string;
procedure Register(const ID: Integer; AClass: TClass);
end;
...
function TRegisterClass.FindID(AClass: TClass): Integer;
begin
Assert(Assigned(AClass));
Result := -1;
if FList.IndexOf(AClass.ClassName) <> -1 then
Result := Integer(FList.Objects[FList.IndexOf(AClass.ClassName)]);
end;
function TRegisterClass.FindClassName(const ID: Integer): string;
var
I: Integer;
begin
Result := EmptyStr;
for I := 0 to Pred(FList.Count) do
if Integer(FList.Objects[I]) = ID then
begin
Result := FList[I];
Exit;
end;
end;
procedure TRegisterClass.Register(const ID: Integer; AClass: TClass);
begin
if IsAlreadyRegistered(ID) then
raise Exception.Create('Duplicate ID Registration')
else if IsAlreadyRegistered(AClass) then
raise Exception.Create('Duplicate Class Registration');
FList.AddObject(AClass.ClassName, Pointer(ID));
end;
Run Code Online (Sandbox Code Playgroud)
请注意,有一个更好的结构可以将String映射到整数.在没有编译器的情况下编写这个并且不了解Delphi5之外的许多基本结构,我选择了一个明显的实现.
请注意,仍然必须编写IsAlreadyRegistered重载函数