我想要使用类函数进行类型转换.我有基(TBase),派生(TDer)和类型转换(TMyType)类.
Ver:Delphi 7
TBase = class;
TDer = class;
TMyType = class;
TBase = class
function Say : String;
class function MYType:TMyType;
end;
TDer = class(TBase)
a: string;
b: string;
function Say2 : String;
end;
TMyType=class(TBase)
class function AsDer:TDer;
end;
{ TBase }
class function TBase.MYType: TMyType;
begin
Result:=TMyType(Self);
end;
function TBase.Say: String;
begin
Result:='TBase';
end;
{ TDer }
function TDer.Say2: String;
begin
Result:='TDer';
end;
{ TMyType }
class function TMyType.AsDer: TDer;
begin
Assert(Assigned(Self));
Result := TDer(Self) ;
end;
Run Code Online (Sandbox Code Playgroud)
示例用法如下,它是调用方法,但是当设置/获取字段的引发错误时.
procedure TForm1.Button1Click(Sender: TObject);
var
b,c:TBase;
begin
b:=TDer.Create;
c:=b.MYType.AsDer;
ShowMessage(b.MYType.AsDer.Say2); // OK. Running
if (@b<>@c) then ShowMessage('Not Equal'); // Shows message, Why ?
b.MYType.AsDer.a:='hey'; // Error
FreeAndNil(b);
end;
Run Code Online (Sandbox Code Playgroud)
你有什么主意吗?
根本问题在于:
class function TBase.MYType: TMyType;
begin
Result:=TMyType(Self);
end;
Run Code Online (Sandbox Code Playgroud)
这是一个类方法,因此Self引用类而不是实例.将它作为一个实例进行转换并不是这样.在您的AsDer类函数中完全相同的错误.
调查具体情况,致电
b.MYType.AsDer.Say2
Run Code Online (Sandbox Code Playgroud)
是良性的,似乎工作正常,因为它没有提到Self.你可以同样写TDer(nil).Say2,代码也可以正常工作.现在,如果Say2引用的函数(称为Self实例)将会出现运行时错误.
@b<>@c
Run Code Online (Sandbox Code Playgroud)
始终计算结果为true,因为您正在比较两个不同局部变量的位置.
b.MYType.AsDer.a
Run Code Online (Sandbox Code Playgroud)
是运行时错误,因为AsDer不返回实例TDer.因此,当您尝试写入时,a您会遇到运行时错误.这是因为你指Self的是这个代码失败的原因,但之前的调用Say2没有.
我不确定你在这里想做什么,但看起来都错了.即使您使用的是实例方法而不是类方法,将基类实例用于派生类实例也是错误的.如果某些东西是错误的类型,任何数量的铸件都不会将其变成正确的类型.
此外,您永远不应该编写具有TBase假设类型的方法的代码TDerived.基类应该完全不知道它的派生类.这是OOP设计的基本原则之一.