[英]How to Inherit from a base datamodule in Delphi7
I created a base datamodule as such: 我这样创建了一个基本数据模块:
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;
...
I intended to inherit other datamodules from dmi_generic, so, in another unit... 我打算从dmi_generic继承其他数据模块,因此,在另一个单元中...
Edit1 编辑1
uses
dmi_Generic;
...
type
TdmUserSecurity = class(TdmiGeneric)
...
var
dmUserSecurity: TdmUserSecurity;
and in my main form... 以我的主要形式
uses
UserSecurityDM;
...
procedure TfmMain.actUserManagerExecute(Sender: TObject);
begin
dmUserSecurity := TdmUserSecurity.OpenDM(Self.Name,dmUserSecurity,TdmUserSecurity);
//some code
TdmUserSecurity.CloseDM(Self.Name,dmUserSecurity);
end;
Edit2: ...which gives compile error "Incompatible type. 'TdmUserSecurity' and 'TdmiGeneric'" Edit2: ...这会产生编译错误“不兼容的类型。'TdmUserSecurity'和'TdmiGeneric'”
How do I fix this, properly? 如何正确解决此问题? Do I typecast the return value at the main form, or is there something I should change at the dmi_generic unit?
我应该在主表单中键入返回值,还是应该在dmi_generic单元中更改某些内容? TIA
TIA
OpenDM()
returns a TdmiGeneric
pointer. OpenDM()
返回一个TdmiGeneric
指针。 But dmUserSecurity
is not declared as TdmiGeneric
, so you will get an error on this assignment: 但是
dmUserSecurity
没有声明为TdmiGeneric
,因此您将在此分配上收到错误消息:
dmUserSecurity := TdmUserSecurity.OpenDM(...);
You would need a type-cast to fix that, either: 您可能需要进行类型转换以解决此问题,或者:
dmUserSecurity := TdmUserSecurity(TdmUserSecurity.OpenDM(...));
Or: 要么:
dmUserSecurity := TdmUserSecurity.OpenDM(...) as TdmUserSecurity;
BTW, why does OpenDM()
have a dm
parameter at all? 顺便说一句,为什么
OpenDM()
完全具有dm
参数? It is useless in the code you showed. 您显示的代码中没有用。 You should either:
您应该:
pass it by var
and get rid of Result
通过
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;
get rid of dm
as a parameter and declare it as a local variable instead: 删除
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;
Either way, since you are calling OpenDM()
on the TdmUserSecurity
class and not on the TdmGeneric
class, you might consider using the Self
class type inside of OpenDM()
, then you can remove the dmClass
parameter: 无论哪种方式,因为你在呼唤
OpenDM()
在TdmUserSecurity
类,而不是在TdmGeneric
类,您可以考虑使用Self
内部类类型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;
Or: 要么:
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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.