我的顶级类是TBaseDB,它有一个后代TCommonDB(并且TCommonDB将有多个后代,例如TProdDBTDevDB)。

让我们在每个类定义中创建一个称为Test1的函数。现在,它只是做一个ShowMessage('Some literal')来告诉我正在执行什么代码。

我直到运行时才知道类的类型。我想要通用的代码,但行为不同。

我想要的是这样的:

var
  MyObj: TBaseDB;
begin
  //pseudo-code...
  if RadioButton1.Checked then
    MyObj := TBaseDB.Create
  else
    MyObj := TCommonDB.create;
  MyObj.Test1;
end;


我似乎无法使它正常工作,并且我想它在我的类定义中。应该如何定义Test1,以便:


我可以将变量声明为TBaseDB
创建的类可以是TBaseDBTCommonDB,并且
是否根据实例是Test还是TBaseDB调用正确的TCommonDB过程?

最佳答案

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TFruit = class
  public
    procedure ShowMessage; virtual; abstract;
  end;

  TApple = class(TFruit)
  public
    procedure ShowMessage; override;
  end;

  TOrange = class(TFruit)
  public
    procedure ShowMessage; override;
  end;


{ TApple }

procedure TApple.ShowMessage;
begin
  Writeln('I''m an apple!');
end;

{ TOrange }

procedure TOrange.ShowMessage;
begin
  Writeln('I''m an orange!');
end;

var
  fruit: TFruit;

begin

  fruit := TApple.Create;

  fruit.ShowMessage;

  Writeln('Press Enter to continue.');
  Readln;

end.


关键字abstract允许您在基类中根本没有任何实现。但是,您也可以在那里实现:

program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TFruit = class
  public
    procedure ShowMessage; virtual;
  end;

  TApple = class(TFruit)
  public
    procedure ShowMessage; override;
  end;

  TOrange = class(TFruit)
  public
    procedure ShowMessage; override;
  end;


{ TFruit }

procedure TFruit.ShowMessage;
begin
  Writeln('I''m a fruit.');
end;

{ TApple }

procedure TApple.ShowMessage;
begin
  inherited;
  Writeln('I''m an apple!');
end;

{ TOrange }

procedure TOrange.ShowMessage;
begin
  inherited;
  Writeln('I''m an orange!');
end;

var
  fruit: TFruit;

begin

  fruit := TApple.Create;

  fruit.ShowMessage;

  Writeln('Press Enter to continue.');
  Readln;

end.


练习:


在每种情况下,如果创建TFruit的实例会怎样?
在第二种情况下,inheritedTApple.ShowMessage中的TOrange.ShowMessage是什么意思?他们是否需要处于流程的顶部?如果您省略它们会怎样?

10-04 18:38