Delphi中的继承机制
程序员文章站
2022-03-03 18:42:01
...
继承是面向对象开发的的特点之一。良好的继承可以有效的降低代码冗余,提高代码复用。Delphi做为一款优秀的面向对象开发工具,在这一方面也不示弱。当我们在Delphi中新建一个窗体时,可以看到如下代码
type
TForm1=class(TForm)
private
{Privatedeclarations}
public
{Publicdeclarations}
end;
TForm1=class(TForm)
private
{Privatedeclarations}
public
{Publicdeclarations}
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;
procedureFormClose(Sender:TObject;varAction:TCloseAction);
procedureFormCreate(Sender:TObject);
procedureactNewExecute(Sender:TObject);
procedureactDeleteExecute(Sender:TObject);
procedureactExitExecute(Sender:TObject);
procedureactNewUpdate(Sender:TObject);
procedureactDeleteUpdate(Sender:TObject);
procedureactExitUpdate(Sender:TObject);
procedureaqActiveAfterInsert(DataSet:TDataSet);
procedureactRefreshUpdate(Sender:TObject);
procedureactRefreshExecute(Sender:TObject);
procedureactCancelExecute(Sender:TObject);
procedureactCancelUpdate(Sender:TObject);
procedureactSaveExecute(Sender:TObject);
procedureactSaveUpdate(Sender:TObject);
procedureaqActivePostError(DataSet:TDataSet;E:EDatabaseError;
varAction:TDataAction);
private
{Privatedeclarations}
procedureOpenDataSet;
procedureCloseDataSet;
protected
public
{Publicdeclarations}
end;
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;
procedureFormClose(Sender:TObject;varAction:TCloseAction);
procedureFormCreate(Sender:TObject);
procedureactNewExecute(Sender:TObject);
procedureactDeleteExecute(Sender:TObject);
procedureactExitExecute(Sender:TObject);
procedureactNewUpdate(Sender:TObject);
procedureactDeleteUpdate(Sender:TObject);
procedureactExitUpdate(Sender:TObject);
procedureaqActiveAfterInsert(DataSet:TDataSet);
procedureactRefreshUpdate(Sender:TObject);
procedureactRefreshExecute(Sender:TObject);
procedureactCancelExecute(Sender:TObject);
procedureactCancelUpdate(Sender:TObject);
procedureactSaveExecute(Sender:TObject);
procedureactSaveUpdate(Sender:TObject);
procedureaqActivePostError(DataSet:TDataSet;E:EDatabaseError;
varAction:TDataAction);
private
{Privatedeclarations}
procedureOpenDataSet;
procedureCloseDataSet;
protected
public
{Publicdeclarations}
end;
在子类中,可以使用关键字Override改写祖先类中使用Virtual关键字声明虚方法。如果在改写的方法只是想在父类的执行之后增加些自己的处理,而不是完全覆盖掉父类中的代码,可以使用inherited关键字。
destructorTCollectionItem.Destroy;
begin
SetCollection(nil);
inheritedDestroy;
end;
begin
SetCollection(nil);
inheritedDestroy;
end;
点型的用法就是在李维的《Inside VCL(深入核心--VCL架构剖析》一书中曾提到过的三明治法。
destructorTStringList.Destroy;
begin
FOnChange:=nil;
FOnChanging:=nil;
inheritedDestroy;
ifFCount<>0thenFinalize(FList^[0],FCount);
FCount:=0;
SetCapacity(0);
end;
begin
FOnChange:=nil;
FOnChanging:=nil;
inheritedDestroy;
ifFCount<>0thenFinalize(FList^[0],FCount);
FCount:=0;
SetCapacity(0);
end;
在Delphi中没有像C++那样的多继承,即每个类只可以有一个父类。不过在Delphi中也可以通过接口(Interface)来实现这种多继承,确切的说这并不是多继承,只是看起来像是多继承。如Delphi中的所有组件的祖先类TComponent。
TComponent=class(TPersistent,IInterface,IInterfaceComponentReference)
private
............
{IInterfaceComponentReference}
functionIInterfaceComponentReference.GetComponent=IntfGetComponent;
functionIntfGetComponent:TComponent;
protected
............
{IInterface}
private
............
{IInterfaceComponentReference}
functionIInterfaceComponentReference.GetComponent=IntfGetComponent;
functionIntfGetComponent:TComponent;
protected
............
{IInterface}
functionQueryInterface(constIID:TGUID;outObj):HResult;virtual;stdcall;
function_AddRef:Integer;stdcall;
function_Release:Integer;stdcall;
{IDispatch}
functionGetTypeInfoCount(outCount:Integer):HResult;stdcall;
functionGetTypeInfo(Index,LocaleID:Integer;outTypeInfo):HResult;stdcall;
functionGetIDsOfNames(constIID:TGUID;Names:Pointer;
NameCount,LocaleID:Integer;DispIDs:Pointer):HResult;stdcall;
functionInvoke(DispID:Integer;constIID:TGUID;LocaleID:Integer;
Flags:Word;varParams;VarResult,ExcepInfo,ArgErr:Pointer):HResult;stdcall;
public
constructorCreate(AOwner:TComponent);virtual;
destructorDestroy;override;
............
propertyComObject:IUnknownreadGetComObject;
propertyComponents[Index:Integer]:TComponentreadGetComponent;
propertyComponentCount:IntegerreadGetComponentCount;
propertyComponentIndex:IntegerreadGetComponentIndexwriteSetComponentIndex;
propertyComponentState:TComponentStatereadFComponentState;
propertyComponentStyle:TComponentStylereadFComponentStyle;
propertyDesignInfo:LongintreadFDesignInfowriteFDesignInfo;
propertyOwner:TComponentreadFOwner;
propertyVCLComObject:PointerreadFVCLComObjectwriteFVCLComObject;
published
propertyName:TComponentNamereadFNamewriteSetNamestoredFalse;
propertyTag:LongintreadFTagwriteFTagdefault0;
end;
function_AddRef:Integer;stdcall;
function_Release:Integer;stdcall;
{IDispatch}
functionGetTypeInfoCount(outCount:Integer):HResult;stdcall;
functionGetTypeInfo(Index,LocaleID:Integer;outTypeInfo):HResult;stdcall;
functionGetIDsOfNames(constIID:TGUID;Names:Pointer;
NameCount,LocaleID:Integer;DispIDs:Pointer):HResult;stdcall;
functionInvoke(DispID:Integer;constIID:TGUID;LocaleID:Integer;
Flags:Word;varParams;VarResult,ExcepInfo,ArgErr:Pointer):HResult;stdcall;
public
constructorCreate(AOwner:TComponent);virtual;
destructorDestroy;override;
............
propertyComObject:IUnknownreadGetComObject;
propertyComponents[Index:Integer]:TComponentreadGetComponent;
propertyComponentCount:IntegerreadGetComponentCount;
propertyComponentIndex:IntegerreadGetComponentIndexwriteSetComponentIndex;
propertyComponentState:TComponentStatereadFComponentState;
propertyComponentStyle:TComponentStylereadFComponentStyle;
propertyDesignInfo:LongintreadFDesignInfowriteFDesignInfo;
propertyOwner:TComponentreadFOwner;
propertyVCLComObject:PointerreadFVCLComObjectwriteFVCLComObject;
published
propertyName:TComponentNamereadFNamewriteSetNamestoredFalse;
propertyTag:LongintreadFTagwriteFTagdefault0;
end;
注:后三段代码均摘自Delphi的Class.pas单元文件。
版权声明:本文为博主原创文章,未经博主允许不得转载。