【问题标题】:Inherited class override virtual method dependency继承类覆盖虚方法依赖
【发布时间】:2013-11-13 10:39:07
【问题描述】:

我有这两个类:

type
  TMyBaseClass = class
  protected
    FAllowDoSomething: Boolean; // initialized to False
    procedure DoSomething; virtual;
  end;

  TMyChildClass = class(TMyBaseClass)
  protected
    procedure DoSomething; override;
  end;

implementation

procedure TMyBaseClass.DoSomething;
begin
  if not FAllowDoSomething then Exit; // Abort;
  ShowMessage('TMyBaseClass: FAllowDoSomething is False. You wont see me!');
end;

procedure TMyChildClass.DoSomething;
begin
  inherited; // Must inherit
  // if not FAllowDoSomething then Exit; { I don't want to check here again }
  ShowMessage('TMyChildClass: FAllowDoSomething is False but still I can see this message!');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TMyBaseClass.Create do try
    DoSomething;
  finally
    Free;
  end;    

  // if I use Abort in TMyBaseClass, the code will not get here

  with TMyChildClass.Create do try
    DoSomething;
  finally
    Free;
  end;
end;

TMyChildClass.DoSomething 我必须inherited TMyBaseClass.DoSomething 但我希望它尊重if not FAllowDoSomething then <don't do anything>

我曾尝试在TMyBaseClass 中使用Abort,但我意识到这不是一个好主意,并且会破坏调用方法(TForm1.Button1Click);

这样做的正确方法是什么,而不在TMyChildClass中写if not FAllowDoSomething then Exit 再次

【问题讨论】:

    标签: delphi delphi-7


    【解决方案1】:

    关键是在基类中对布尔值执行一次检查。因此,将 DoSomething 设为非虚拟并在您的基类中实现它,如下所示:

    procedure TMyBaseClass.DoSomething;
    begin
      if FAllowDoSomething then
        DoSomethingImplementation;
    end;
    

    其中 DoSomethingImplementation 是您在派生类中重写的虚拟方法。

    基类如下所示:

    type
      TMyBaseClass = class
      private
        FAllowDoSomething: Boolean;
      protected
        procedure DoSomethingImplementation; virtual;
      public
        procedure DoSomething;
      end;
    

    您的派生类如下所示:

    type
      TMyDerivedClass = class(TMyBaseClass)
      protected
        procedure DoSomethingImplementation; override;
      end;
    

    您的重写方法如下所示:

    procedure TMyDerivedClass.DoSomethingImplementation;
    begin
      inherited;
      ShowMessage(...);
    end;
    

    【讨论】:

    • +1 如果您希望基类在子类代码之前和/或之后执行某些内容,这通常是一种非常常见的模式。这些方法对通常称为Foo(非虚拟)和DoFoo(虚拟)
    • +10 非常好,而且如此微不足道! :) 还为@jpfollenius +1 提到了 Foo 和 DoFoo(我一直在想如何命名这些方法以及使用什么约定)。
    • 是的,命名。我受到您选择 DoSomething 的限制。不想写 DoDoSomerthing。
    • @David,我同意。下次我会使用MakeSomthing 或简单的Foo :)
    • 有人知道这种模式是怎么叫的吗?我经常使用它,想知道它是否有任何名称。 :)
    【解决方案2】:

    您需要捕获Abort 异常。

    procedure TMyBaseClass.DoSomething;
    begin
      if not FAllowDoSomething then Abort;
      ShowMessage('TMyBaseClass: FAllowDoSomething is False. You wont see me!');
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      with TMyBaseClass.Create do
      try
        try
          DoSomething;
        finally
          Free;
        end;    
      except
        on EAbort do ;
      end;
    
      // the code will get here
    
      with TMyChildClass.Create do
      try
        try
          DoSomething;
        finally
          Free;
        end;    
      except
        on EAbort do ;
      end;
    end;
    

    【讨论】:

    • 哎哟!!最好希望没有其他人愿意使用 Abort。
    猜你喜欢
    • 1970-01-01
    • 2012-11-20
    • 1970-01-01
    • 2014-01-15
    • 2012-09-27
    • 1970-01-01
    • 2023-03-27
    • 2020-09-08
    • 2016-01-24
    相关资源
    最近更新 更多