Унаследованная зависимость класса от переопределения класса

У меня есть эти 2 класса:

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>.

Я попытался использовать Abort в TMyBaseClass, но я понимаю, что это не очень хорошая идея и нарушит вызывающий метод (TForm1.Button1Click);

Каков правильный подход к этому, не записывая if not FAllowDoSomething then Exit снова в TMyChildClass.

Ответ 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;

Ответ 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;