调用class种不同形式的函数
Calling class functions of different forms
我有一个应用程序,其中包括 "main" 表格以及其他四种表格(formA、formB、formC、formD)。四种形式中的每一种都有唯一的 class function execute()
.
现在,在 formD 中,我放置了一个编辑框和一个按钮。在按钮的 OnClick
事件中,根据我在编辑框中传递的表单名称,我想 运行 适当的 class 函数。
我试图通过创建一个 TDictionary
来实现这个任务,我在其中添加了 3 对值,但是没有成功。具体来说,我做了以下事情:
unit FormDU;
interface
type
TFormD = class(TForm)
Edit1: TEdit;
fcShapeBtn1: TfcShapeBtn;
.............
.............
public
class function execute:boolean;
..........
..........
end;
var
FormD: TFormD;
MyList:TDictionary<string,TForm>;
implementation
class function TFormD.execute:boolean;
begin
FormD:= TFormD.Create(nil);
MyList:= TDictionary<string,TForm>.create;
MyList.Add('FormA',TFormA);
MyList.Add('FormB',TFormB);
MyList.Add('FormC',TFormC);
FormD.showmodal;
end;
procedure TFormD.fcShapeBtn1Click(Sender: TObject);
begin
// Here I check whether the text in Edit1 box has the value of one of the
// keys that are included in the MyList dictionary and if yes I want to
// trigger the class function execute of the appropriate form...
if MyList.ContainsKey(Edit1.text) then // suppose that text= formA
MyList.Items[Edit1.text].execute // which doesn't work....
// I thought that the 'Items' method of the dictionary would return back
// to me the appropriate form type - which is connected to the specific
// key - and thus I could call each form's class function execute()
end;
我不知道如何解决这个问题。
你的方法有两个问题:
你的 TDictionary
被声明为保存 TForm
对象指针,但你的代码试图插入 TForm
派生的 class 类型。那将无法编译。
您的表单 class 不是从具有 Execute()
方法供它们覆盖的公共基础 class 派生的。因此,您不能只从 TDictionary
中检索一个值并直接调用 Execute
。您将不得不求助于使用 RTTI 来查找和调用 Execute()
。
有一些可能的方法可以解决这个问题:
从公共基础 class 中导出您的表单 classes,并将该基础 class 的派生词存储在您的 TDictionary
中:
unit FormBaseU;
interface
uses
Forms;
type
TFormBase = class(TForm)
public
class function Execute: Boolean; virtual;
end;
TFormBaseClass = class of TFormBase;
implementation
class function TFormBase.Execute: Boolean;
begin
Result := False;
end;
end.
unit FormDU;
interface
uses
..., FormBaseU;
type
TFormD = class(TFormBase)
Edit1: TEdit;
fcShapeBtn1: TfcShapeBtn;
...
public
class function Execute: Boolean; override;
...
end;
var
FormD: TFormD;
MyList: TDictionary<string, TFormBaseClass>;
implementation
uses
FormAU, FormBU, FormCU;
class function TFormD.Execute: Boolean;
begin
MyList := TDictionary<string, TFormBaseClass>.Create;
// make sure TFormA, TFormB, and TFormC all derive
// from TFormBase and override Execute() ...
MyList.Add('FormA', TFormA);
MyList.Add('FormB', TFormB);
MyList.Add('FormC', TFormC);
FormD := TFormD.Create(nil);
FormD.ShowModal;
FormD.Free;
end;
procedure TFormD.fcShapeBtn1Click(Sender: TObject);
var
FormClass: TFormBaseClass;
begin
if MyList.TryGetValue(Edit1.Text, FormClass) then
FormClass.Execute;
end;
做类似的事情,但使用 interface
而不是基础 class(这只适用于对象,而不适用于 class 类型):
unit MyIntfU;
interface
type
IMyIntf = interface
['{41BEF2B6-C27F-440E-A88B-9E5CF8840034}']
function Execute: Boolean;
end;
implementation
end.
unit FormDU;
interface
uses
..., MyIntfU;
type
TFormD = class(TForm, MyIntf)
Edit1: TEdit;
fcShapeBtn1: TfcShapeBtn;
...
public
function Execute: Boolean;
...
end;
var
FormD: TFormD;
MyList: TDictionary<string, TForm>;
implementation
uses
FormAU, FormBU, FormCU;
function TFormD.Execute: Boolean;
begin
MyList := TDictionary<string, TForm>.Create;
// make sure TFormA, TFormB, and TFormC are all
// instantiated beforehand and implement IMyIntf ...
MyList.Add('FormA', FormA);
MyList.Add('FormB', FormB);
MyList.Add('FormC', FormC);
FormD := TFormD.Create(nil);
FormD.ShowModal;
FormD.Free;
end;
procedure TFormD.fcShapeBtn1Click(Sender: TObject);
var
Form: TForm;
Intf: IMyIntf;
begin
if MyList.TryGetValue(Edit1.Text, Form) then
begin
if Supports(Form, IMyIntf, Intf) then
Intf.Execute;
end;
end;
根本不要将 classes/objects 存储在您的 TDictionary
中,而是存储实际的 class 方法:
unit FormDU;
interface
uses
...;
type
TFormD = class(TForm)
Edit1: TEdit;
fcShapeBtn1: TfcShapeBtn;
...
public
class function Execute: Boolean;
...
end;
TMyClassMethod = function: Boolean of object;
var
FormD: TFormD;
MyList: TDictionary<string, TMyClassMethod>;
implementation
uses
FormAU, FormBU, FormCU;
class function TFormD.Execute: Boolean;
begin
MyList := TDictionary<string, TMyClassMethod>.Create;
MyList.Add('FormA', TFormA.Execute);
MyList.Add('FormB', TFormB.Execute);
MyList.Add('FormC', TFormC.Execute);
FormD := TFormD.Create(nil);
FormD.ShowModal;
FormD.Free;
end;
procedure TFormD.fcShapeBtn1Click(Sender: TObject);
var
Meth: TMyClassMethod;
begin
if MyList.TryGetValue(Edit1.Text, Meth) then
Meth;
end;
我有一个应用程序,其中包括 "main" 表格以及其他四种表格(formA、formB、formC、formD)。四种形式中的每一种都有唯一的 class function execute()
.
现在,在 formD 中,我放置了一个编辑框和一个按钮。在按钮的 OnClick
事件中,根据我在编辑框中传递的表单名称,我想 运行 适当的 class 函数。
我试图通过创建一个 TDictionary
来实现这个任务,我在其中添加了 3 对值,但是没有成功。具体来说,我做了以下事情:
unit FormDU;
interface
type
TFormD = class(TForm)
Edit1: TEdit;
fcShapeBtn1: TfcShapeBtn;
.............
.............
public
class function execute:boolean;
..........
..........
end;
var
FormD: TFormD;
MyList:TDictionary<string,TForm>;
implementation
class function TFormD.execute:boolean;
begin
FormD:= TFormD.Create(nil);
MyList:= TDictionary<string,TForm>.create;
MyList.Add('FormA',TFormA);
MyList.Add('FormB',TFormB);
MyList.Add('FormC',TFormC);
FormD.showmodal;
end;
procedure TFormD.fcShapeBtn1Click(Sender: TObject);
begin
// Here I check whether the text in Edit1 box has the value of one of the
// keys that are included in the MyList dictionary and if yes I want to
// trigger the class function execute of the appropriate form...
if MyList.ContainsKey(Edit1.text) then // suppose that text= formA
MyList.Items[Edit1.text].execute // which doesn't work....
// I thought that the 'Items' method of the dictionary would return back
// to me the appropriate form type - which is connected to the specific
// key - and thus I could call each form's class function execute()
end;
我不知道如何解决这个问题。
你的方法有两个问题:
你的
TDictionary
被声明为保存TForm
对象指针,但你的代码试图插入TForm
派生的 class 类型。那将无法编译。您的表单 class 不是从具有
Execute()
方法供它们覆盖的公共基础 class 派生的。因此,您不能只从TDictionary
中检索一个值并直接调用Execute
。您将不得不求助于使用 RTTI 来查找和调用Execute()
。
有一些可能的方法可以解决这个问题:
从公共基础 class 中导出您的表单 classes,并将该基础 class 的派生词存储在您的
TDictionary
中:unit FormBaseU; interface uses Forms; type TFormBase = class(TForm) public class function Execute: Boolean; virtual; end; TFormBaseClass = class of TFormBase; implementation class function TFormBase.Execute: Boolean; begin Result := False; end; end.
unit FormDU; interface uses ..., FormBaseU; type TFormD = class(TFormBase) Edit1: TEdit; fcShapeBtn1: TfcShapeBtn; ... public class function Execute: Boolean; override; ... end; var FormD: TFormD; MyList: TDictionary<string, TFormBaseClass>; implementation uses FormAU, FormBU, FormCU; class function TFormD.Execute: Boolean; begin MyList := TDictionary<string, TFormBaseClass>.Create; // make sure TFormA, TFormB, and TFormC all derive // from TFormBase and override Execute() ... MyList.Add('FormA', TFormA); MyList.Add('FormB', TFormB); MyList.Add('FormC', TFormC); FormD := TFormD.Create(nil); FormD.ShowModal; FormD.Free; end; procedure TFormD.fcShapeBtn1Click(Sender: TObject); var FormClass: TFormBaseClass; begin if MyList.TryGetValue(Edit1.Text, FormClass) then FormClass.Execute; end;
做类似的事情,但使用
interface
而不是基础 class(这只适用于对象,而不适用于 class 类型):unit MyIntfU; interface type IMyIntf = interface ['{41BEF2B6-C27F-440E-A88B-9E5CF8840034}'] function Execute: Boolean; end; implementation end.
unit FormDU; interface uses ..., MyIntfU; type TFormD = class(TForm, MyIntf) Edit1: TEdit; fcShapeBtn1: TfcShapeBtn; ... public function Execute: Boolean; ... end; var FormD: TFormD; MyList: TDictionary<string, TForm>; implementation uses FormAU, FormBU, FormCU; function TFormD.Execute: Boolean; begin MyList := TDictionary<string, TForm>.Create; // make sure TFormA, TFormB, and TFormC are all // instantiated beforehand and implement IMyIntf ... MyList.Add('FormA', FormA); MyList.Add('FormB', FormB); MyList.Add('FormC', FormC); FormD := TFormD.Create(nil); FormD.ShowModal; FormD.Free; end; procedure TFormD.fcShapeBtn1Click(Sender: TObject); var Form: TForm; Intf: IMyIntf; begin if MyList.TryGetValue(Edit1.Text, Form) then begin if Supports(Form, IMyIntf, Intf) then Intf.Execute; end; end;
根本不要将 classes/objects 存储在您的
TDictionary
中,而是存储实际的 class 方法:unit FormDU; interface uses ...; type TFormD = class(TForm) Edit1: TEdit; fcShapeBtn1: TfcShapeBtn; ... public class function Execute: Boolean; ... end; TMyClassMethod = function: Boolean of object; var FormD: TFormD; MyList: TDictionary<string, TMyClassMethod>; implementation uses FormAU, FormBU, FormCU; class function TFormD.Execute: Boolean; begin MyList := TDictionary<string, TMyClassMethod>.Create; MyList.Add('FormA', TFormA.Execute); MyList.Add('FormB', TFormB.Execute); MyList.Add('FormC', TFormC.Execute); FormD := TFormD.Create(nil); FormD.ShowModal; FormD.Free; end; procedure TFormD.fcShapeBtn1Click(Sender: TObject); var Meth: TMyClassMethod; begin if MyList.TryGetValue(Edit1.Text, Meth) then Meth; end;