如何从 Delphi7 中的基本数据模块继承
How to Inherit from a base datamodule in Delphi7
我这样创建了一个基础数据模块:
unit dmi_Generic;
...
type
TDMGenericClass = class of TdmiGeneric;
TdmiGeneric = class(TDataModule)
private
ReferencedForms: FormIDTypes;
public
class procedure CloseDM(FormName: string; dm: TdmiGeneric);
class function OpenDM(FormName: string; dm: TdmiGeneric; const dmClass:
TDMGenericClass): TdmiGeneric;
end;
...
class function TdmiGeneric.OpenDM(FormName: string; dm: TdmiGeneric; const
dmClass: TDMGenericClass):
TdmiGeneric;
var
FormID: Integer;
begin
FormID := GetFormID(FormName);
if dm = nil then
dm := dmClass.Create(nil); //trouble is probably born here
with dm do
if not (FormID in ReferencedForms) then
ReferencedForms := ReferencedForms + [FormID];
Result := dm;
end;
...
我打算从 dmi_generic 继承其他数据模块,所以,在另一个单元中...
编辑1
uses
dmi_Generic;
...
type
TdmUserSecurity = class(TdmiGeneric)
...
var
dmUserSecurity: TdmUserSecurity;
在我的主要形式中...
uses
UserSecurityDM;
...
procedure TfmMain.actUserManagerExecute(Sender: TObject);
begin
dmUserSecurity := TdmUserSecurity.OpenDM(Self.Name,dmUserSecurity,TdmUserSecurity);
//some code
TdmUserSecurity.CloseDM(Self.Name,dmUserSecurity);
end;
编辑2:
...给出编译错误 "Incompatible type. 'TdmUserSecurity' and 'TdmiGeneric'"
我该如何正确解决这个问题?我是在主窗体中输入 return 值,还是应该在 dmi_generic 单元中更改某些内容? TIA
OpenDM()
returns 一个 TdmiGeneric
指针。但是 dmUserSecurity
没有被声明为 TdmiGeneric
,所以你会在这个赋值上得到一个错误:
dmUserSecurity := TdmUserSecurity.OpenDM(...);
你需要一个类型转换来解决这个问题,要么:
dmUserSecurity := TdmUserSecurity(TdmUserSecurity.OpenDM(...));
或:
dmUserSecurity := TdmUserSecurity.OpenDM(...) as TdmUserSecurity;
顺便说一句,为什么 OpenDM()
有一个 dm
参数?它在您显示的代码中没有用。您应该:
通过var
传递它并摆脱Result
unit dmi_Generic;
...
type
TdmiGeneric = class;
TDMGenericClass = class of TdmiGeneric;
TdmiGeneric = class(TDataModule)
private
...
public
...
class procedure CloseDM(FormName: string; var dm: TdmiGeneric);
class procedure OpenDM(FormName: string; const dmClass: TDMGenericClass; var dm: TDMGeneric);
end;
...
class procedure TdmiGeneric.OpenDM(FormName: string; const dmClass: TDMGenericClass; var dm: TdmiGeneric);
var
...
begin
...
if dm = nil then
dm := dmClass.Create(nil);
with dm do
...
end;
class procedure TdmiGeneric.CloseDM(FormName: string; var dm: TdmiGeneric);
begin
FreeAndNil(dm);
end;
uses
UserSecurityDM;
...
procedure TfmMain.actUserManagerExecute(Sender: TObject);
begin
TdmUserSecurity.OpenDM(Self.Name, TdmUserSecurity, TdmiGeneric(dmUserSecurity));
//some code
TdmUserSecurity.CloseDM(Self.Name, TdmiGeneric(dmUserSecurity));
end;
摆脱作为参数的 dm
并将其声明为局部变量:
unit dmi_Generic;
...
type
TdmiGeneric = class;
TDMGenericClass = class of TdmiGeneric;
TdmiGeneric = class(TDataModule)
private
...
public
...
class procedure CloseDM(FormName: string; var dm: TDMGeneric);
class function OpenDM(FormName: string; const dmClass: TDMGenericClass): TDMGeneric;
end;
...
class function TdmiGeneric.OpenDM(FormName: string; const dmClass: TDMGenericClass): TdmiGeneric;
var
dm: TDMGeneric;
...
begin
...
dm := dmClass.Create(nil);
with dm do
...
Result := dm;
end;
class procedure TdmiGeneric.CloseDM(FormName: string; var dm: TDMGeneric);
begin
FreeAndNil(dm);
end;
uses
UserSecurityDM;
...
procedure TfmMain.actUserManagerExecute(Sender: TObject);
begin
dmUserSecurity := TdmUserSecurity.OpenDM(Self.Name, TdmUserSecurity) as TdmUserSecurity;
//some code
TdmUserSecurity.CloseDM(Self.Name, TdmiGeneric(dmUserSecurity));
end;
无论哪种方式,由于您是在 TdmUserSecurity
class 而不是 TdmGeneric
class 上调用 OpenDM()
,您可以考虑使用 Self
class 在 OpenDM()
里面输入,然后你可以去掉 dmClass
参数:
unit dmi_Generic;
...
type
TdmiGeneric = class;
TDMGenericClass = class of TdmiGeneric;
TdmiGeneric = class(TDataModule)
private
...
public
...
class procedure OpenDM(FormName: string; var dm: TdmiGeneric);
end;
...
class procedure TdmiGeneric.OpenDM(FormName: string; var dm: TdmiGeneric);
var
...
begin
...
if dm = nil then
begin
if Self = TdmiGeneric then
raise Exception.Create('Must call OpenDM() on a descendant class type').
dm := TDMGenericClass(Self).Create(nil);
end;
with dm do
...
end;
uses
UserSecurityDM;
...
procedure TfmMain.actUserManagerExecute(Sender: TObject);
begin
TdmUserSecurity.OpenDM(Self.Name, TdmiGeneric(dmUserSecurity));
...
end;
或:
unit dmi_Generic;
...
type
TdmiGeneric = class;
TDMGenericClass = class of TdmiGeneric;
TdmiGeneric = class(TDataModule)
private
...
public
...
class function OpenDM(FormName: string): TDMGeneric;
end;
...
class function TdmiGeneric.OpenDM(FormName: string): TdmiGeneric;
var
dm: TDMGeneric;
...
begin
...
if Self = TdmiGeneric then
raise Exception.Create('Must call OpenDM() on a descendant class type').
dm := TDMGenericClass(Self).Create(nil);
with dm do
...
Result := dm;
end;
uses
UserSecurityDM;
...
procedure TfmMain.actUserManagerExecute(Sender: TObject);
begin
dmUserSecurity := TdmUserSecurity.OpenDM(Self.Name) as TdmUserSecurity;
...
end;
我这样创建了一个基础数据模块:
unit dmi_Generic;
...
type
TDMGenericClass = class of TdmiGeneric;
TdmiGeneric = class(TDataModule)
private
ReferencedForms: FormIDTypes;
public
class procedure CloseDM(FormName: string; dm: TdmiGeneric);
class function OpenDM(FormName: string; dm: TdmiGeneric; const dmClass:
TDMGenericClass): TdmiGeneric;
end;
...
class function TdmiGeneric.OpenDM(FormName: string; dm: TdmiGeneric; const
dmClass: TDMGenericClass):
TdmiGeneric;
var
FormID: Integer;
begin
FormID := GetFormID(FormName);
if dm = nil then
dm := dmClass.Create(nil); //trouble is probably born here
with dm do
if not (FormID in ReferencedForms) then
ReferencedForms := ReferencedForms + [FormID];
Result := dm;
end;
...
我打算从 dmi_generic 继承其他数据模块,所以,在另一个单元中...
编辑1
uses
dmi_Generic;
...
type
TdmUserSecurity = class(TdmiGeneric)
...
var
dmUserSecurity: TdmUserSecurity;
在我的主要形式中...
uses
UserSecurityDM;
...
procedure TfmMain.actUserManagerExecute(Sender: TObject);
begin
dmUserSecurity := TdmUserSecurity.OpenDM(Self.Name,dmUserSecurity,TdmUserSecurity);
//some code
TdmUserSecurity.CloseDM(Self.Name,dmUserSecurity);
end;
编辑2: ...给出编译错误 "Incompatible type. 'TdmUserSecurity' and 'TdmiGeneric'"
我该如何正确解决这个问题?我是在主窗体中输入 return 值,还是应该在 dmi_generic 单元中更改某些内容? TIA
OpenDM()
returns 一个 TdmiGeneric
指针。但是 dmUserSecurity
没有被声明为 TdmiGeneric
,所以你会在这个赋值上得到一个错误:
dmUserSecurity := TdmUserSecurity.OpenDM(...);
你需要一个类型转换来解决这个问题,要么:
dmUserSecurity := TdmUserSecurity(TdmUserSecurity.OpenDM(...));
或:
dmUserSecurity := TdmUserSecurity.OpenDM(...) as TdmUserSecurity;
顺便说一句,为什么 OpenDM()
有一个 dm
参数?它在您显示的代码中没有用。您应该:
通过
var
传递它并摆脱Result
unit dmi_Generic; ... type TdmiGeneric = class; TDMGenericClass = class of TdmiGeneric; TdmiGeneric = class(TDataModule) private ... public ... class procedure CloseDM(FormName: string; var dm: TdmiGeneric); class procedure OpenDM(FormName: string; const dmClass: TDMGenericClass; var dm: TDMGeneric); end; ... class procedure TdmiGeneric.OpenDM(FormName: string; const dmClass: TDMGenericClass; var dm: TdmiGeneric); var ... begin ... if dm = nil then dm := dmClass.Create(nil); with dm do ... end; class procedure TdmiGeneric.CloseDM(FormName: string; var dm: TdmiGeneric); begin FreeAndNil(dm); end;
uses UserSecurityDM; ... procedure TfmMain.actUserManagerExecute(Sender: TObject); begin TdmUserSecurity.OpenDM(Self.Name, TdmUserSecurity, TdmiGeneric(dmUserSecurity)); //some code TdmUserSecurity.CloseDM(Self.Name, TdmiGeneric(dmUserSecurity)); end;
摆脱作为参数的
dm
并将其声明为局部变量:unit dmi_Generic; ... type TdmiGeneric = class; TDMGenericClass = class of TdmiGeneric; TdmiGeneric = class(TDataModule) private ... public ... class procedure CloseDM(FormName: string; var dm: TDMGeneric); class function OpenDM(FormName: string; const dmClass: TDMGenericClass): TDMGeneric; end; ... class function TdmiGeneric.OpenDM(FormName: string; const dmClass: TDMGenericClass): TdmiGeneric; var dm: TDMGeneric; ... begin ... dm := dmClass.Create(nil); with dm do ... Result := dm; end; class procedure TdmiGeneric.CloseDM(FormName: string; var dm: TDMGeneric); begin FreeAndNil(dm); end;
uses UserSecurityDM; ... procedure TfmMain.actUserManagerExecute(Sender: TObject); begin dmUserSecurity := TdmUserSecurity.OpenDM(Self.Name, TdmUserSecurity) as TdmUserSecurity; //some code TdmUserSecurity.CloseDM(Self.Name, TdmiGeneric(dmUserSecurity)); end;
无论哪种方式,由于您是在 TdmUserSecurity
class 而不是 TdmGeneric
class 上调用 OpenDM()
,您可以考虑使用 Self
class 在 OpenDM()
里面输入,然后你可以去掉 dmClass
参数:
unit dmi_Generic;
...
type
TdmiGeneric = class;
TDMGenericClass = class of TdmiGeneric;
TdmiGeneric = class(TDataModule)
private
...
public
...
class procedure OpenDM(FormName: string; var dm: TdmiGeneric);
end;
...
class procedure TdmiGeneric.OpenDM(FormName: string; var dm: TdmiGeneric);
var
...
begin
...
if dm = nil then
begin
if Self = TdmiGeneric then
raise Exception.Create('Must call OpenDM() on a descendant class type').
dm := TDMGenericClass(Self).Create(nil);
end;
with dm do
...
end;
uses
UserSecurityDM;
...
procedure TfmMain.actUserManagerExecute(Sender: TObject);
begin
TdmUserSecurity.OpenDM(Self.Name, TdmiGeneric(dmUserSecurity));
...
end;
或:
unit dmi_Generic;
...
type
TdmiGeneric = class;
TDMGenericClass = class of TdmiGeneric;
TdmiGeneric = class(TDataModule)
private
...
public
...
class function OpenDM(FormName: string): TDMGeneric;
end;
...
class function TdmiGeneric.OpenDM(FormName: string): TdmiGeneric;
var
dm: TDMGeneric;
...
begin
...
if Self = TdmiGeneric then
raise Exception.Create('Must call OpenDM() on a descendant class type').
dm := TDMGenericClass(Self).Create(nil);
with dm do
...
Result := dm;
end;
uses
UserSecurityDM;
...
procedure TfmMain.actUserManagerExecute(Sender: TObject);
begin
dmUserSecurity := TdmUserSecurity.OpenDM(Self.Name) as TdmUserSecurity;
...
end;