具有类功能的类型转换

zgn*_*zgn -1 delphi casting

我想要使​​用类函数进行类型转换.我有基(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)

你有什么主意吗?

Dav*_*nan 6

根本问题在于:

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设计的基本原则之一.