1. 程式人生 > >Delphi中的繼承機制

Delphi中的繼承機制

        繼承是面向物件開發的的特點之一。良好的繼承可以有效的降低程式碼冗餘,提高程式碼複用。Delphi做為一款優秀的面向物件開發工具,在這一方面也不示弱。當我們在Delphi中新建一個窗體時,可以看到如下程式碼

type
  TForm1 
=class(TForm)
  
private
    
{ Private declarations }
  
public
    
{ Public declarations }
  end;

這表示我們建立的所有窗體都是繼承自TForm這個類。如果我們希望在某個專案中所有的窗體都具有相同的風格和字型標準,大不必為每個窗體一一指定,只需要定義一個標準的窗體作為專案中所有窗體的基類就可以了,這樣我們只要在這個基類的窗體中定義窗體風格和字型標準即可應用到所有它的子類窗體中。假設我們設計一個MDI專案,希望所有的MDI窗體都具有相同的介面佈局,就可以先建立一個MDI窗體基類,然後讓所有的MDI窗體都從此類派生,而非TForm類。

  TfrmMDIBase =class(TForm)
    CoolBar1: TCoolBar;
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    dsActive: TDataSource;
    ToolButton6: TToolButton;
    ToolButton7: TToolButton;
    ToolButton8: TToolButton;
    ToolButton9: TToolButton;
    ToolButton10: TToolButton;
    ActionList1: TActionList;
    DataSetFirst1: TDataSetFirst;
    DataSetPrior1: TDataSetPrior;
    DataSetNext1: TDataSetNext;
    DataSetLast1: TDataSetLast;
    DBGridEh1: TDBGridEh;
    aqActive: TADOQuery;
    actNew: TAction;
    actEdit: TAction;
    actExit: TAction;
    actDelete: TAction;
    ToolButton11: TToolButton;
    actRefresh: TAction;
    Panel1: TPanel;
    pnlEdit: TPanel;
    actCancel: TAction;
    ToolButton12: TToolButton;
    actSave: TAction;
    ToolButton13: TToolButton;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure actNewExecute(Sender: TObject);
    procedure actDeleteExecute(Sender: TObject);
    procedure actExitExecute(Sender: TObject);
    procedure actNewUpdate(Sender: TObject);
    procedure actDeleteUpdate(Sender: TObject);
    procedure actExitUpdate(Sender: TObject);
    procedure aqActiveAfterInsert(DataSet: TDataSet);
    procedure actRefreshUpdate(Sender: TObject);
    procedure actRefreshExecute(Sender: TObject);
    procedure actCancelExecute(Sender: TObject);
    procedure actCancelUpdate(Sender: TObject);
    procedure actSaveExecute(Sender: TObject);
    procedure actSaveUpdate(Sender: TObject);
    procedure aqActivePostError(DataSet: TDataSet; E: EDatabaseError;
      var Action: TDataAction);
  
private
    
{ Private declarations }
    procedure OpenDataSet;
    procedure CloseDataSet;
  
protected
  
public
    
{ Public declarations }
  end;

        在子類中,可以使用關鍵字Override改寫祖先類中使用Virtual關鍵字宣告虛方法。如果在改寫的方法只是想在父類的執行之後增加些自己的處理,而不是完全覆蓋掉父類中的程式碼,可以使用inherited關鍵字。

destructor TCollectionItem.Destroy;
begin
  SetCollection(nil);
  inherited Destroy;
end;

點型的用法就是在李維的《Inside VCL(深入核心--VCL架構剖析》一書中曾提到過的三明治法。

destructor TStringList.Destroy;
begin
  FOnChange :
= nil;
  FOnChanging :
= nil;
  inherited Destroy;
  
if FCount <>0 then Finalize(FList^[0], FCount);
  FCount :
=0;
  SetCapacity(
0);
end;

        在Delphi中沒有像C++那樣的多繼承,即每個類只可以有一個父類。不過在Delphi中也可以通過介面(Interface)來實現這種多繼承,確切的說這並不是多繼承,只是看起來像是多繼承。如Delphi中的所有元件的祖先類TComponent。

  TComponent =class(TPersistent, IInterface, IInterfaceComponentReference)
  
private
        ............
    { IInterfaceComponentReference }
    function IInterfaceComponentReference.GetComponent 
= IntfGetComponent;
    function IntfGetComponent: TComponent;
  
protected        ............    { IInterface }     function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;

    
{ IDispatch }
    function GetTypeInfoCount(
out Count: Integer): HResult; stdcall;
    function GetTypeInfo(Index, LocaleID: Integer; 
out TypeInfo): HResult; stdcall;
    function GetIDsOfNames(
const IID: TGUID; Names: Pointer;
      NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
    function Invoke(DispID: Integer; 
const IID: TGUID; LocaleID: Integer;
      Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;

  
public
    constructor Create(AOwner: TComponent); 
virtual;
    destructor Destroy; 
override;
        ............

    property ComObject: IUnknown read GetComObject;

    property Components[Index: Integer]: TComponent read GetComponent;
    property ComponentCount: Integer read GetComponentCount;
    property ComponentIndex: Integer read GetComponentIndex write SetComponentIndex;
    property ComponentState: TComponentState read FComponentState;
    property ComponentStyle: TComponentStyle read FComponentStyle;
    property DesignInfo: Longint read FDesignInfo write FDesignInfo;
    property Owner: TComponent read FOwner;

    property VCLComObject: Pointer read FVCLComObject write FVCLComObject;

  published
    property Name: TComponentName read FName write SetName stored False;
    property Tag: Longint read FTag write FTag 
default0;
  end;

注:後三段程式碼均摘自Delphi的Class.pas單元檔案。