Delphi重載,覆蓋,多態


一、override  重載
type
  TFigure = class
    procedure Draw; virtual;//(我的理解是)父類中可以使用父類的,子類中使用子類的。與“四”是有區別的。
  end;
  TRectangle = class(TFigure)
    procedure Draw; override;//a1
  end;
  TEllipse = class(TFigure)
    procedure Draw; override;//a2
  end;
使用
var
  Figure: TFigure;
begin
  Figure := TRectangle.Create;
  Figure.Draw;  // 執行a1
  Figure.Destroy;
  Figure := TEllipse.Create;
  Figure.Draw;  // 執行a2
end;
 
二、overload 多態
  procedure foo(i: integer); overload;
  procedure foo(d: double);  overload;
  procedure foo(v: variant); overload;
典型用法。如果是對於繼承的。必須使用reintroduce
type
  T1 = class(TObject)
    procedure Test(I: Integer); overload; virtual;
  end;
  T2 = class(T1)
    procedure Test(S: string); reintroduce; overload;
  end;
   ...
  SomeObject := T2.Create;
  SomeObject.Test('Hello!');  // T2.Test
  SomeObject.Test(7);         // T1.Test
 
三、override & inherited
override是用來重載父類的procedure,
如果父類是virtual 或者 dynamic 方法的,就可以使用inherited,來調用父類中的代碼。
 
四、abstract
procedure DoSomething; virtual; abstract;//如果是這個樣式的,表示要在子類中實現(代碼)。而父類中,其他procedure function可以使用這個procedure。
(這里的virtual似乎不能被dynamic替換)。
使用procedure DoSomething; virtual; abstract;和procedure DoSomething; virtual;的區別就是,前者的實現代碼在子類,而后者實現代碼在自身。后者可以在子類中override一下,使其子類也有自己的實現代碼。
2009-4-11
在最近的代碼中發現(不知道是不是D7的緣故)
procedure DoSomething; virtual; abstract;
procedure DoSomething; dynamic; abstract;
都是可以的。
而且在繼承類中也可以不寫實現代碼。
在基類中如果要判斷有沒有被繼承類寫實現代碼的方式不是
if Assigned(DoSomething) then ...
而是
if MethodAddress('DoSomething')<>nil then...
 
五、reintroduce
覆蓋父類中的virtual 方式的內容。(編譯器不會提示“xxx 被hide了”)
 
六、static
默認就是這個。
我們常打 procedure test(xx:Integer);其實就是static的。
這個比較好理解。
如果子類中,聲明了一個test,跟父類無關。各自用各自的。
除非使用強制轉換。比如:
type
  TFigure = class
    procedure Draw;
  end;
  TRectangle = class(TFigure)
    procedure Draw;
  end;
//實現
var
  Figure: TFigure;
  Rectangle: TRectangle;
begin
  Figure := TFigure.Create;
  Figure.Draw;  // 父類用父類的 TFigure.Draw
  Figure.Destroy;
  Figure := TRectangle.Create;
  Figure.Draw;  // 雖然初始化為子類,但是由於申明的是父類,所以Figure還是調用了父類的Draw  TFigure.Draw
  TRectangle(Figure).Draw;  // 強制轉換成子類,就可以用TRectangle.Draw
  Figure.Destroy;
  Rectangle := TRectangle.Create;
  Rectangle.Draw;  // 子類用子類的 TRectangle.Draw
  Rectangle.Destroy;
end;
 
七、forward declaration提前定義。
用於類被提前使用。注意fd的class后面要立即加“;”不能使用括號和基類。
type
  TFigure = class;  // forward declaration
  TDrawing = class
    Figure: TFigure;
     ...
  end;
  TFigure = class  // defining declaration
    Drawing: TDrawing;
     ...
  end;
 
八、virtualdynamic
虛擬方法占用的內存大,調用速度快;動態方法相反。
如今,哪有PC內存不夠的。
所以,筆者建議,就使用virtual吧。
2009-04-07
我知道了,內存是有不夠用的時候。
所以這里修改說法,需要來回調用的用virtual,一般只用到1,2次的用dynamic。
像筆者一般寫一個基類函數,只用一次,所以大部分都改成dynamic了。
但是有個地方必須要用virtual
private
  FItem:Integer
  procedure SetItem(Value:Integer);virtual;//dynamic不允許
public
  property Item:Integer;read FItem write SetItem;
end;

參考:http://www.cnblogs.com/key-ok/p/3380401.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM