程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi中的類和對象

Delphi中的類和對象

編輯:Delphi
談談Delphi中的類和對象
  1.登不了大雅之堂地理解幾個概念
     說到類和對象,我們不能不提及這樣幾個概念:類,對象,實例。就我個人覺得可
  以這樣來理解:對象指的是泛稱,自然界的任何實體都可以看成一個對象;而類則是
  以這些對象某些特征而分成的一系列的種類;實例則是特指屬於某一個類的一個對象。
  好啦,這些大道理我就不用多說了。不如來一個“背道而馳”的作法,我們用Delphi
  code 來闡述這些外國人提出的一些令我們中國人不好理解的概念吧:
  var
    ABtn:TButton;
  定義ABtn是屬於TButton類的一個對象,但ABtn不能說是一個實例,因為它還沒有
  被創建,所以我們說這是定義了一個對象,如果說定義了一個實例,多多少少有
  一些不夠確切。:)
  begin
    ABtn:=TButton.Create(Self);//創建一個TButton的實例
    ABtn.Caption:='對象';
    ABtn.Free;
  end;

  2.對象是一個地地道道的指針
     從物理角度來看,對象就是一段地址空間,這段地址空間的標志就是我們定義的
  類“變量”。所以我們可以把對象看成一個類的指針。大家知道,要訪問一個指針就
  必須對指針初始化。對象的既然是一個指針,也必須對它進行初始化。如何初始化呢?
  還是說指針的初始化吧。對於一個指針可以有以下兩種方法來進行初始化:
  (一)直接分配
  var
    Pint:^Integer;
  begin
    new(Pint);
    Pint^:=12;
    Dispose(Pint);
  end;
  (二)指向別的已分配空間的變量
  var
    Pint:^Integer;
    i:integer;
  begin
    i:=12;
    Pint:=@i;
  end;
  有趣的是,對象這種“指針”也有兩種方法初始化
  (一)直接分配
  var
    AForm:TForm;
  begin
    AForm:=TForm.Create(Self);
    AForm.ShowModal;
    AForm.Free;
  end;
  (二)指向別的已分配空間的實例
  var
    AForm:TForm;
  begin
    AForm:=Self;
    AForm.Caption:='知道了嗎?為什麼會這樣呢';
  end;
  file://這個AForm和它所指向的Form實例共用同一段地址單元,所有對AForm操作都將反應
  file://到它所對應的Form實例之上。
  說到這,我們就很好解釋為什麼過程(函數)的對象參數傳遞時,象這樣這的格式:
  (一)procedure SetEdit(var Edit:TEdit);
      begin
        Edit.Text:='11';
      end;
  和
  (二)procedure SetEdit(Edit:TEdit);
      begin
        Edit.Text:='11';
      end;
  效果是一樣的了。(一)是把一個TEdit實體作為參數引用的形式進行參數傳遞,(二)是
  把一個TEdit的對象“指針”作為參數傳遞。

  3.類可以理解成一種特殊的數據類型
      我們知道數據類型可以進行強制類型轉化,類即然可以理解成一種數據類型,那
  麼它也應該可以進行類類型轉。比方如下代碼為一個按鈕(Button1)的單擊事件:
  (一)
  procedure TForm1.Button1Click(Sender: TObject);
  var
    ACaption:String;
  begin
    ACaption:=TButton(Sender).Caption;//Sender從TObject轉化到TButton
    ShowMessage(Format('You clicked ''%s'' !',[ACaption]));
  end;
  在這段代碼中,Sender是一個TObject型對象,我們把它強制轉化為TButton類型。如你
  看得不清楚,可以參照一下我們通常的數據類型的轉化:
  (二)
  procedure TForm1.Button1Click(Sender: TObject);
  var
    S_Str:String;
    P_Str:PChar;
  begin
    S_Str:='I love China!';
    P_Str:=PChar(S_Str);
    S_Str:='';
    S_Str:=String(P_Str);
    ShowMessage(S_Str);
  end;
  但是在面對對象的程序設計過程中,強調的是安全性,如(一)的強制類型轉化存在著不
  安全性。如下的代碼,依然是寫Button1.OnClick事件:
  (三)
  procedure TForm1.Button1Click(Sender: TObject);
  begin
    TCanvas(Sender).Brush.Color:=clRed;
  end;
  執行一下,就會出錯。這樣豈不是違背了面對對象的程序設計的宗旨了嗎?沒有,即然
  是類,就應該有類特定的類強制轉化方法,改(三)的方法如下:
  (四)
  procedure TForm1.Button1Click(Sender: TObject);
  begin
    (Sender as TCanvas).Brush.Color:=clRed;
  end;//用as來轉化,as就可以把錯誤抓住,不會影響程序的正常運行。
  說到這我順便提一下VB吧,如果學過VB的人可能覺得其中的控件數組比較爽,尤其是在
  編寫象計算器這樣的程序時。但Delphi給我們什麼呢?答案是Delphi也能快速簡潔的開
  發出這樣的程序。如是操作:在窗體上放一個Edit和十個Button,把Button.Caption分
  別設為'0','1','2',...'9',然後寫一個按鈕的OnClick事件如下:
  (五)
  procedure TForm1.Button1Click(Sender: TObject);
  begin
    Edit1.Text:=Edit1.Text+(Sender as TButton).Caption;
  end;
  把別的Button的OnClick事件都關聯到Button1Click上,運行程序。拍拍手!這樣計算器
  程序的雛形就具備了。我們用Delphi的類類型轉化,開發出來類似VB中的控件數組功能
  的程序也是很棒的嘛!:)

  4.抽象類和它的實例
      Delphi中有一種類為抽象類,你不能天真的直接為它創建一個實例。如:TStrings
  類。如下代碼:
  (一)
  var
    StrLst:TStrings;
  begin
    StrLst:=TStrings.Create;
    StrLst.Add('I love Japan!');
    StrLst.Free;
  end;
  這是不對的。那如何為諸如TStrings這樣的抽象類構造實例呢?答案是借助它的非抽
  象子類。我們知道TStrings有一個TStringList非抽象子類。我們就可以這樣作:
  (二)
  var
    StrLst:TStrings;
  begin
    StrLst:=TStringList.Create;//借助其子類的構造器,對StrLst進行子類化
    StrLst.Add('I love China!');
    StrLst.Free;
  end;
  (三)
  var
    StrLst:TStringList;
  begin
    StrLst:=TStringList.Create;
  file://放棄吧,不要再用抽象類,完全用它的“兒子”來你的事吧 
    StrLst.Add('I love China!');
    StrLst.Free;
  end;

  5.類是一種對數據和操作高度的封裝機制
  (一)數據封裝
  unit Unit2;

  interface
  type
    TEmployee=class
    private
      FName:String;
    public
      Constructor Create;
      function  GetName:String;
      procedure SetName(AName:String);
    end;
  implementation

  { TEmployee }

  constructor TEmployee.Create;
  begin
    FName:='BlazingFire';
  end;

  function TEmployee.GetName: String;
  begin
    Result:=FName;
  end;

  procedure TEmployee.SetName(AName: String);
  begin
    FName:=AName;
  end;

  end.
  如上代碼,我們就用了一個過程SetName和一個函數GetName對私有變量FName進行完全的
  封裝。我們要對FName操作就只有這樣:
  uses
    unit2;
  procedure TForm1.Button1Click(Sender: TObject);
  var
    AEmployee:TEmployee;
  begin
    AEmployee:=TEmployee.Create;
    AEmployee.SetName('Rose');//利用SetName來設置FName
    MessageBox(Handle,PChar(AEmployee.GetName),'Empoyee',0);
    file://用GetName來訪問FName
    AEmployee.Free;
  end;
  (二)操作封裝
  unit Unit2;

  interface
  type
    TDivision=Class
    public
      file://多態性讓你的程序更據有“柔韌性”
      function GetDiv(Num1,Num2:Double):Double;overload;
      function GetDiv(Num1,Num2:integer):integer;overload;
    end;
  implementation

  { Division }

  function TDivision.GetDiv(Num1, Num2: Double): Double;
  begin
    try
      Result:=Num1/Num2;
    except
      Result:=0;//提供彈形處理機制,處理除數為0情況
    end;
  end;

  function TDivision.GetDiv(Num1, Num2: integer): integer;
  begin
    try
      Result:=Num1 div Num2;
    except
      Result:=0;//提供彈形處理機制,處理除數為0情況
    end;
  end;

  end.
  如上代碼我們通過類的多態性機制把除法分別處理成整除和非整除,又通過異常處理屏
  去除數為0的情況,從而保證操作的安全性,在調用時,我們就可以這樣來:
  uses
    unit2;
  {$R *.dfm}

  procedure TForm1.Button1Click(Sender: TObject);
  var
    Division:TDivision;
    IValue:integer;
    FValue:Double;
  begin
    Division:=TDivision.Create;
    IValue:=Division.GetDiv(1,2);
    FValue:=Division.GetDiv(1.0,2);
    IValue:=Division.GetDiv(1,0);
    FValue:=Division.GetDiv(1.0,0);
    Division.Free;
  end;
   
  6.類是一種代碼重用機制
      比方在5中我們想對這個類加上一個GetAdd函數來作加法運算就可以用類的繼承。如
  下寫就可以了:
  (一)
  unit Unit2;

  interface
  type
    TDivision=Class
    public
      function GetDiv(Num1,Num2:Double):Double;overload;
      function GetDiv(Num1,Num2:integer):integer;overload;
    end;
  type
    TOperation=Class(TDivision)
    public
      function GetAdd(Num1,Num2:Double):Double;
    end;
  implementation

  { Division }

  function TDivision.GetDiv(Num1, Num2: Double): Double;
  begin
    try
      Result:=Num1/Num2;
    except
      Result:=0;
    end;
  end;

  function TDivision.GetDiv(Num1, Num2: integer): integer;
  begin
    try
      Result:=Num1 div Num2;
    except
      Result:=0;
    end;
  end;

  { TOperation }

  function TOperation.GetAdd(Num1, Num2: Double): Double;
  begin
    Result:=Num1+Num2;
  end;

  end.
  這裡我們從TDivision繼承了一個子類TOperation。TOperation就可以即有TDivsion
  公有方法GetDiv,又有自己的獨特的方法GetAdd。這是類為我們提供的“魚和熊掌兼
  得”之法。不錯吧。:)

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved