Delphi的類和對象(四)- 類的方法


方法是在類中定義的且包裝在類中的函數或過程,用於執行類的操作,完成類的任務。一個類的方法決定了通過這個類創建的實例行為,

一個類的所有方法決定了這個實例所執行的功能。類中的所有函數或過程都可以成為類的方法。

在Delphi 中子程序包含過程和函數兩種表現形式,而方法通過這兩種形式演變出 6種不同的形態。

(1)過程方法和函數方法:

    依附於某個特定的類,在某個類的聲明中定義並根據可見性進行調用,如果過程方法或函數方法被聲明成私有的,則他只能在這個類的實例中調用。

    與一般過程和函數一樣,過程方法沒有返回值,函數方法具有返回值。

(2)構造方法與析構方法:

    主要作用就是用於創建和釋放類的對象,參考類和對象(一)有記錄。

(3)類過程方法和類函數方法:

    類過程方法和類函數方法與過程方法和函數方法基本相同,不同的地方在於過程方法和函數方法必須在類的某個對象實例化之后才可使用。

    而類過程方法和類函數方法的操作對象不是類的對象而是類本身,所以不用通過對象來引用,類本身就可以引用類過程方法和類函數方法。

    當一個類的對象經常要調用類中的一個方法時,而這個方法又不需要使用類中所定義的變量,就可以將這個方法定義為類方法。

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
    class function GetformName: String;
    class procedure SetFormName(FormName: string);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

class function TForm1.GetformName: String;
begin
  Result:= Form1.Name;
end;

class procedure TForm1.SetFormName(FormName: string);
begin
  Form1.Name:= FormName;
end;

end.

 

在類中的方法按其功能分為靜態方法,虛方法,動態方法。

(1)靜態方法:靜態方法是最常用的一種方法,如果不在方法聲明時特意指定關鍵字,所聲明的方法都是靜態方法。

    當靜態方法被聲明時,編譯器就會為這個方法指定一個地址。當調用這個方法時就是就會通過這個地址進行調用。靜態方法是調用最快的一種。

    如果在父類定義一個靜態方法,子類繼承這個方法時只是將父類的這個方法地址賦予給了子類,所以子類繼承的方法調用的還是父類方法。

    當子類中定義了一個和父類同名的靜態方法時,子類的靜態方法將覆蓋父類的靜態方法。當子類調用這個靜態方法,調用的是自身的方法。

 

(2)虛方法:虛方法的聲明只需要在方法聲明的后面加上 virtual 關鍵字,父類中定義好虛方法之后,如果子類中定義了一個同名的方法,那么調用時子類的方法就不會像

    靜態方法那樣去覆蓋父類的同名方法,而是在繼承父類原有方法的基礎上展現自身方法的特性。對虛方法的覆蓋也叫重載(override)。

    靜態方法的地址是固定的,虛方法的地址在編譯器編譯時是不會指定的,而是在程序運行時通過動態查找而制定的,所以虛方法調用時會比虛方法要快。

    虛方法的調用是通過一個虛擬表來實現的,編譯器會為每一個類類型生成一個虛擬表,虛擬表用來存儲虛方法入口地址。一個類只有一個虛擬表,該類的所有對象都會通過這個表調用虛方法。

    當類中的某個對象被創建時,編譯器會為這個對象指定所屬類的虛擬表,而指向這個虛擬表的指針存儲在對象地址的前4 個字節中,如果類中沒有定義虛方法,此時指向虛擬表的指針將設為空。

 

(3)動態方法:動態方法與虛方法在語意以及使用上都是一樣的,只是存儲方式不同,動態方法也有相應的地址表,叫做動態方法表。動態方法的定義是在方法聲明時最后加 dynamic 。

    一般情況下在子類中經常覆蓋父類的方法時可使用虛方法,而不經常覆蓋父類的方法時就使用動態方法。因為虛方法的執行效率要高於動態方法,而動態方法又比較節省空間。 

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  TMyClass = class   {定義類; 雖然這個類沒有什么實際意義, 但就是一個類了}
    d: TDate;
  end;

//父類
  TParent = class
  protected
    function MyFun(i: Integer): Integer; dynamic;  //動態方法
    procedure MyProc; virtual;  //虛方法
  end;

//子類
  TChild = class(TParent)
  protected
    function MyFun(i: Integer): Integer; override;  //覆蓋
    procedure MyProc; override;  //覆蓋
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TParent }

function TParent.MyFun(i: Integer): Integer;
begin
  Inc(i);
  Result := i;
end;

procedure TParent.MyProc;
begin
  ShowMessage('Parent');
end;

{ TChild }

function TChild.MyFun(i: Integer): Integer;
begin
  i := inherited MyFun(i);  //先調用夫類方法,被 +1;當然也可以不調用
  Inc(i);                   //子類再 +1
  Result := i;
end;

procedure TChild.MyProc;
begin
  inherited;  //先調用夫類方法;當然也可以不調用
  ShowMessage('Child');
end;

//測試
procedure TForm1.FormCreate(Sender: TObject);
var
  p: TParent;
  c: TChild;
begin
  p := TParent.Create;
  c := TChild.Create;

  p.MyProc;  //Parent
  c.MyProc;  //Parent; TChild

  ShowMessage(IntToStr(p.MyFun(2)));  //3
  ShowMessage(IntToStr(c.MyFun(2)));  //4

  p.Free;
  c.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyCls: TMyClass;  {聲明一個類變量, 也就是對象}
begin
  {使用類}
  MyCls := TMyClass.Create;              {需要先手動建立, 因為類需要實例化為對象才可以使用}

  MyCls.d := Now;                        {2008-1-11}
  ShowMessage(DateToStr(MyCls.d));
  ShowMessage(IntToStr(SizeOf(MyCls)));  {4; 怎么會是4? 因為 MyCls 對象只是一個指針!}

  MyCls.Free;                            {用完后釋放}
end;

end.

 

 

在虛方法和動態方法的基礎上還有一個方法叫做抽象方法(abstract)抽象方法的定義只是在虛方法與動態方法的標識符后秒加 abstract 標識符。

在類的聲明中包含了抽象方法,那么此類也稱為抽象類,它是一種特殊的專門為父類所定義的處於層次結構較為上層的類。在設計類的結構時,如果想將具有共性的

功能抽象成一個類的話,就可以將這個類聲明為抽象類。而對於抽象類的可見性最好是設置成受保護的。

抽象方法不同於普通的方法,不具備方法體,在父類定義,子類實現。否則程序不能調用的。

unit Unit1;

interface

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

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

{父類,抽象類 Delphi中的抽象類只定義行為的類,它規定了由此派生的類必須具備某些行為。但是抽象類不實現這些行為,而必須由其派生類去實現這些行為。所以,它只是一種“抽象”的類,而且,我們無法為抽象類創建實例。}
  TParent = class
  protected
    function MyFun(i: Integer): Integer; virtual; abstract;
    //抽象方法(純虛方法),只有定義沒有實現,一個類包含一個即成抽象類,抽象類不能直接創建對象。
  end;

//子類
  TChild = class(TParent)
  protected
    function MyFun(i: Integer): Integer; override;  //覆蓋
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TChild }

function TChild.MyFun(i: Integer): Integer;
begin
  Inc(i);
  Result := i;
end;

//測試
procedure TForm1.FormCreate(Sender: TObject);
var
  p: TParent;
  c: TChild;
begin
  p := TChild.Create;  //抽象類只能通過其子類創建對象
  c := TChild.Create;

  ShowMessage(IntToStr(p.MyFun(2)));  //3
  ShowMessage(IntToStr(c.MyFun(2)));  //3

  p.Free;
  c.Free;
end;

end.

 


免責聲明!

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



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