我基本上有这个对象结构:
TJSONStructure = class(TObject);
TReqBase = class(TJSONStructure)
private
token: Int64;
public
procedure FillWithTemplateData; virtual;
end;
TReqLogin = class(TReqBase)
private
username,
password: String;
module : Integer;
public
procedure FillWithTemplateData; override;
end;
procedure TReqBase.FillWithTemplateData;
begin
token := ...;
end;
procedure TReqLogin.FillWithTemplateData;
begin
inherited;
username := ...;
password := ...;
module := ...;
end;
type
TWebAct = (ttlogin,
ttsignin);
TReqClass = class of TReqBase;
const
cWebActStructures: Array[TWebAct] of
record
RequestClass : TReqClass;
end
= (
{ ttlogin } (RequestClass: TReqLogin;),
{ ttsignin } (RequestClass: TReqSignIn;) // Not in definitions above
);
现在我做了:
var
lWebAct : TWebAct;
lRequestClass : TReqClass;
begin
for lWebAct := Low(TWebAct) to High(TWebAct) do
begin
lRequestClass := cWebActStructures[lWebAct].RequestClass;
我想打电话
lRequestClass.FillWithTemplateData;
为了在lWebAct = TReqLogin.FillWithTemplateData
等时执行ttlogin
但它不会编译:{{1}}
我确实理解了原因(编译器消息的文本),但是如何解决这个问题,以便在lWebAct = ttlogin等时执行TReqLogin.FillWithTemplateData,而不必处理TReqLogin,TReqSignIn类型中的TReqSinIn类型代码(再次)?
答案 0 :(得分:2)
lRequestClass
是一个类引用。您可以在其上调用class
方法,但不能调用实例方法。 FillWithTemplateData
是一种实例方法。
您需要有一个实例来调用实例方法。所以实例化一个:
var
req: TReqBase;
....
req := lRequestClass.Create;
try
req.FillWithTemplateData;
...
finally
req.Free;
end;
如果您开发类以便他们需要在构造函数中执行工作,那么您必须向TReqBase
引入虚拟构造函数。并在派生类中覆盖它。这是在从类引用实例化时确保派生构造函数运行的唯一方法。
也许你的系统需要以其他方式实例化实例,我不能从这里说出来。无论如何,无论如何实例化,都需要一个实例来调用实例方法。
答案 1 :(得分:1)
您是否尝试过使用接口参考?
type
IReqBase = Interface(IInterface)
['{B71BD1C3-CE4C-438A-8090-DA6AACF0B3C4}']
procedure FillWithTemplateData;
end;
type
TWebAct = (ttlogin,
ttsignin);
TForm59 = class(TForm)
Button1: TButton;
Memo1: TMemo;
CheckBox1: TCheckBox;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
FReqList: Array of IReqBase;
procedure CreateBaseList;
procedure ClearBaseList;
public
{ Public declarations }
end;
TJSONStructure = class(TInterfacedObject);
TReqBaseClass = class of TReqBase;
TReqBase = class(TJSONStructure, IReqBase)
private
token: Int64;
protected
class function ReqClass: TReqBaseClass; virtual; abstract;
public
Constructor Create; virtual;
procedure FillWithTemplateData; virtual;
class function ReqBase: IReqBase;
end;
TReqLogin = class(TReqBase)
private
Fusername,
Fpassword: String;
Fmodule : Integer;
protected
class function ReqClass: TReqBaseClass; override;
public
Constructor Create; override;
Destructor Destroy; override;
procedure FillWithTemplateData; override;
end;
TReqSignIn = class(TReqBase)
private
Fusername,
Fpassword: String;
Fmodule : Integer;
protected
class function ReqClass: TReqBaseClass; override;
public
Constructor Create; override;
Destructor Destroy; override;
procedure FillWithTemplateData; override;
end;
var
Form59: TForm59;
implementation
{$R *.dfm}
procedure TForm59.Button1Click(Sender: TObject);
begin
Memo1.Lines.Clear;
IReqBase(FReqList[integer(CheckBox1.Checked)]).FillWithTemplateData;
end;
procedure TForm59.Button2Click(Sender: TObject);
begin
CreateBaseList;
end;
procedure TForm59.Button3Click(Sender: TObject);
begin
if CheckBox1.Checked then
TReqSignIn.ReqBase.FillWithTemplateData
else
TReqLogin.ReqBase.FillWithTemplateData;
end;
procedure TForm59.ClearBaseList;
begin
SetLength(FReqList, 0);
end;
procedure TForm59.CreateBaseList;
begin
if High(FReqList) = Ord(High(TWebAct)) +1 then
ClearBaseList;
SetLength(FReqList, Ord(High(TWebAct)) + 1 );
FReqList[ord(ttlogin)] := TReqLogin.ReqBase;
FReqList[ord(ttsignin)] := TReqSignIn.ReqBase;
end;
procedure TForm59.FormCreate(Sender: TObject);
begin
CreateBaseList;
end;
procedure TForm59.FormDestroy(Sender: TObject);
begin
ClearBaseList;
end;
{ TReqLogin }
constructor TReqLogin.Create;
begin
inherited;
FUserName := 'Rick';
FPassword := 'Test';
Fmodule := 100;
end;
destructor TReqLogin.Destroy;
begin
Form59.Memo1.Lines.Add('Destroyed: ' +ClassName);
inherited;
end;
procedure TReqLogin.FillWithTemplateData;
begin
inherited;
Form59.Memo1.Lines.Add(Fusername);
Form59.Memo1.Lines.Add(FPassword);
Form59.Memo1.Lines.Add(IntToStr(FModule));
end;
class function TReqLogin.ReqClass: TReqBaseClass;
begin
Result := TReqLogin;
end;
{ TReqBase }
constructor TReqBase.Create;
begin
inherited;
Token := -1;
end;
procedure TReqBase.FillWithTemplateData;
begin
Form59.Memo1.Lines.Add(IntToStr(Token));
end;
class function TReqBase.ReqBase: IReqBase;
begin
Result := ReqClass.Create;
end;
{ TReqSignIn }
constructor TReqSignIn.Create;
begin
inherited;
FUserName := 'Peterson';
FPassword := 'TestPW';
Fmodule := 101;
end;
destructor TReqSignIn.Destroy;
begin
Form59.Memo1.Lines.Add('Destroyed: ' +ClassName);
inherited;
end;
procedure TReqSignIn.FillWithTemplateData;
begin
inherited;
Form59.Memo1.Lines.Add(Fusername);
Form59.Memo1.Lines.Add(FPassword);
Form59.Memo1.Lines.Add(IntToStr(FModule));
end;
class function TReqSignIn.ReqClass: TReqBaseClass;
begin
Result := TReqSignIn;
end;
end.