How to implement identical methods with 2 and more Classes?

后端 未结 2 1627
一生所求
一生所求 2021-01-18 11:58

I want to write a TCheckBox and TRadioButton descendants having 3 identical methods.

TMyCheckBox = class(TCheckBox)
  procedure DoS         


        
相关标签:
2条回答
  • 2021-01-18 12:41

    You are looking for implementation inheritance rather than interface inheritance. This is only achievable in Delphi if you can derive classes from a single common ancestor. This limitation is inherent because the language only supports single-inheritance.

    The best you can do is something like this:

    type
      TMyWinControlExtender = class
      private
        FTarget: TWinControl;
      public
        constructor Create(Target: TWinControl);
        procedure WMSize(var Message: TWMSize; out CallInherited: Boolean);
        procedure DoSomething;
      end;
    
      TMyCheckBox = class(TCheckBox)
      private
        FExtender: TMyWinControlExtender;
      protected
        procedure WMSize(var Message: TWMSize); message WM_SIZE;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure DoSomething;
      end;
    
      TMyRadioButton = class(TRadioButton)
      private
        FExtender: TMyWinControlExtender;
      protected
        procedure WMSize(var Message: TWMSize); message WM_SIZE;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure DoSomething;
      end;
    
    { TMyWinControlExtender }
    
    constructor TMyWinControlExtender.Create(Target: TWinControl);
    begin
      inherited Create;
      FTarget := Target;
    end;
    
    procedure TMyWinControlExtender.WMSize(var Message: TWMSize; out CallInherited: Boolean);
    begin
      if FTarget.... then
        ....
      CallInherited := ...;
      //etc.
    end;
    
    procedure TMyWinControlExtender.DoSomething;
    begin
      if FTarget.... then
        ....
      //etc.
    end;
    
    { TMyCheckBox }
    
    constructor TMyCheckBox.Create(AOwner: TComponent);
    begin
      inherited;
      FExtender := TMyWinControlExtender.Create(Self);
    end;
    
    destructor TMyCheckBox.Destroy;
    begin
      FExtender.Free;
      inherited;
    end;
    
    procedure TMyCheckBox.DoSomething;
    begin
      FExtender.DoSomething;
    end;
    
    procedure TMyCheckBox.WMSize(var Message: TWMSize);
    var
      CallInherited: Boolean;
    begin
      FExtender.WMSize(Message, CallInherited);
      if CallInherited then
        inherited;
    end;
    

    And likewise for TMyRadioButton etc.

    Now, you could use interfaces and delegation to reduce some of the boilerplate, but there's no way for that to help with a message handler like WMSize.

    0 讨论(0)
  • 2021-01-18 12:50

    Define an interface say IDoSomething with the the three method signatures.

    Then change your class declaration to

    TMyCheckBox = class(TCheckBox, IDoSomething)
    

    and then implement.

    If the implementations are common or very close.

    Then define a helper class TDoSomething and then delegate the work.

    e.g.

    Procedure TMyCheckBox.DoSomething1; // implements IDoSomething1
    Begin
      TDoSomething.DoSomething1(Self); // given class method will suffice.
    End;
    

    Class Methods in delphi, equivalent to static methods in other languages.

    Type
        TDoSomethingHelper = Class(TObject)
        Public
          Class Procedure DoSomething1(aComponent : TComponent);
        End;
    
    ...
    implementation
    
    Class Procedure TDoSomethingHelper.DoSomething1(aComponent : TComponent);
    Begin
      aComponent.Tag = 27;
    End;
    
    0 讨论(0)
提交回复
热议问题