虛擬方法、動態方法、抽象方法、構造方法、方法重載、方法繼承

來源:互聯網
上載者:User

 

虛擬方法

虛擬方法在Delphi中利用關鍵字virtual定義。一個方法被聲明為虛擬方法後,在調用時,程式需要動態地確定需要調用的方法。

現在重新定義上面的方法。需要注意的是此處使用了關鍵字override,表示方法的重載。代碼如下所示:

type

TFigure = class

procedure Draw; virtual;

procedure Destroy

end;

procedure Tfigure.Draw;

begin

writeln('現在調用的是TFigure對象');

end;

type

TRectangle = class(TFigure)

procedure Draw; override;

procedure Destroy

end;

procedure TRectAngle.Draw;

begin

writeln('現在調用的是TRectangle對象');

end;

type

TEllipse = class(TFigure)

procedure Draw; override;

procedure Destroy

end;

procedure TEllipse.Draw;

begin

writeln('現在調用的是TEllipse對象');

end;

下面的代碼調用上述繪圖物件的Draw方法:

var

Figure: TFigure;

begin

Figure := TRectangle.Create;

Figure.Draw; // 調用TRectangle.Draw

Figure.Destroy;

Figure := TEllipse.Create;

Figure.Draw; // 調用TEllipse.Draw

Figure.Destroy;

end;

上述代碼中,第一次調用Figure.Draw時,當前對象是TRectangle類型;第二次調用Figure.Draw時,當前對象是TEllipse類型。

輸出如下:

現在調用的是TRectangle對象

現在調用的是TEllipse對象

動態方法

動態方法利用dynamic關鍵字實現,它的功能與虛擬方法基本類似,不同主要體現在內部實現。與對象虛擬方法建立入口不同的是,dynamic給方法賦了一個數字,並儲存相應代碼的地址。動態方法列表只包含新加的和覆蓋的方法入口,繼承的動態方法的匹配是通過尋找每一個祖先的動態方法列表(按與繼承“反轉的順序”)來實現,因此動態方法用於處理訊息(包括Windows訊息)。實際上,訊息處理過程的匹配方式與動態方法相同,只是定義方法不同。

動態方法沒有對象VMT(Virtal Method Table,虛擬方法表)的入口,它們減少了對象消耗的記憶體數量。匹配動態方法比匹配一般的虛擬方法慢。因此,如果方法調用很頻繁,最好將其定義為虛擬方法。

抽象方法

抽象方法利用關鍵字abstract實現,如果一個方法定義為抽象,則這個方法不需要在本類中實現。而在它的子類中,可以在重載方法中實現相關功能。

在下面代碼中,TFigure對象的Draw方法聲明為抽象,所以不需要實現TFigure.Draw方法,在它的子類中,子類資料根據各自不同的需求重載並實現這個方法。

type

TFigure = class

procedure Draw; virtual;abstract;

procedure Destroy

end;

type

TRectangle = class(TFigure)

procedure Draw; override;

procedure Destroy

end;

procedure TRectangle.Draw;

begin

writeln('現在調用的是TRectangle對象');

end;

type

TEllipse = class(TFigure)

procedure Draw; override;

procedure Destroy

end;

procedure TEllipse.Draw;

begin

writeln('現在調用的是TEllipse對象');

end;

如果一個類的抽象方法沒有被重載,則這個方法是不能被調用的,否則會產生調用抽象方法的內部Delphi錯誤。

 方法重載

 

前面已經指出,通過override(方法重載)可以實現多態。方法重載即指多個方法可以享有相同的名字。通過在後代對象中聲明一個與祖先對象重名的方法,就可以重載一個方法。如果想使這個方法在後代對象中做和祖先對象一樣的工作,但是使用不同的方式,就可以重載這個方法。

如下幾種情況將導致重載失敗:

(1)祖先類中沒有要重載的方法。

(2)要重載的方法在祖先類中被聲明為靜態方法。

(3)要重載的方法的參數類型或個數與祖先類中不同。

 方法繼承

 

Delphi利用關鍵字inherited實現方法之間的互相繼承。

如果inherited關鍵字後面沒有方法名,那麼當前方法就繼承祖先類中與它同名的方法;如果inherited關鍵字後面有方法名,則當前方法就繼承祖先類中指定的方法。

方法繼承經常用在構造方法中,以便子類能夠實現祖先類中的一些預設設定。

 構造方法

 

構造方法是一種特殊的方法,它為新對象分配記憶體並且指向這個新的對象。Delphi中的每個類都有構造方法,用來初始化該類的一個新的對象。

建構函式利用關鍵字constructor來聲明,而建構函式的函數名可以任意選擇,但是Delphi中函數名一般採用Create。建構函式可以用多個,但是Delphi建議每個對象只定義一個建構函式。

Delphi在建構函式內部實現的處理過程包括:

(1)首先在記憶體中開闢一塊地區用於儲存物件。

(2)然後對這塊地區預設初始化設定。初始化,包括有序類型的欄位清零,指標類型和類類型的欄位設定為Nil,字串類型的欄位清為空白等。

(3)執行構造中使用者指定的動作。

(4)返回一個新分配的並初始化了的類類型執行個體。傳回值的類型必須就是類的類型。

建立一個對象的執行個體,需要先調用Create方法,然後建構函式把這個執行個體賦給一個變數。構造方法不返回任何資料類型,在構造方法的實現中,也可以進行方法重載,如下例所示:

type

TShape = class(TGraphicControl)

private

FPen: TPen;

FBrush: TBrush;

procedure PenChanged(Sender: TObject);

procedure BrushChanged(Sender: TObject);

public

constructor Create(Owner: TComponent); override;

destructor Destroy; override;

...

end;

M

constructor TShape.Create(Owner: TComponent);

begin

inherited Create(Owner); // Initialize inherited parts

Width := 65; // Change inherited properties

Height := 65;

FPen := TPen.Create; // Initialize new fields

FPen.OnChange := PenChanged;

FBrush := TBrush.Create;

FBrush.OnChange := BrushChanged;

end;

上述例子中,TShape 類重載了TGraphicControl的建構函式。在建構函式內部,TShape類首先繼承TGraphicControl的預設建構函式,實現一些常規設定,然後通過設定自己的一些特殊參數,實現自己的參數初始化,同時使自己與祖先類有所區別。


又一建構函式執行個體

delphi的建構函式的定義是:
constructor create;
delphi的解構函式的定義是:
destructor destroy;
解構函式是不能重載的,但是建構函式是可以重載的。
建構函式在重載的時候要在後面加“overload”,例如:
constructor create;overload;
constructor create(i:integer);overload;
注意,只有兩個建構函式以上才叫重載,只有一個就不用“overload;”了。
預設的建構函式是:constructor create; 如果有重載的話,那麼預設的建構函式後面也要加overload,正象上面的例子一樣。
delphi建構函式在類外定義在什麼位置呢?在implementation的後面。下面給出一個執行個體,可以從這個執行個體中看出建構函式的定義:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)   
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMyForm1 = class(TForm1)    //自訂一個TMyForm1類
  public
    constructor Create; overload;  //建構函式有重載
    constructor Create(I: Integer); overload; //重載一個建構函式
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
constructor TMyForm1.Create;   //這裡定義建構函式
begin
  inherited Create(nil);  //inherited 表示調用父類的建構函式
end;
constructor TMyForm1.Create(I: Integer);
begin
  inherited Create(nil);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  A: TMyForm1;
begin
  A := TMyForm1.Create(1);
  A.Show;
end;

end.

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.