简体   繁体   English

如何从Delphi7中的基本数据模块继承

[英]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: 您应该:

  1. 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; 
  2. 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM