Delphi中靜態方法重載還是覆蓋的討論

來源:互聯網
上載者:User

Delphi中靜態方法重載還是覆蓋的討論

新人學習Delphi的時候,容易搞不懂的一個問題,當子類方法和基類方法同名,並且參數也一樣的時候,叫做什麼呢?是覆蓋,還是重載呢?

 

答案是隱藏父類方法。

 

一般我們的理解重載是同名,不同參數的同一個類裡面實現,

或者父類和子類方法同名,參數不同,子類必須有overide關鍵字,表示重載方法。

 

也就是說重載必須有overload修飾;

 

覆蓋呢?覆蓋必須有override修改;

 

否則同名,同參數就是隱藏方法。

=================================================================

下面是筆者自己的程式,您可以嘗試一下。

 

program Project2;

 

{$APPTYPE CONSOLE}

 

uses

  SysUtils;

 

  type tclassa=class

     private

       age :Integer;

     public

       function getage:integer;   //靜態方法

       function getDat:integer;  //靜態方法

       end;

 

       tclassb=class(tclassa)

       private

 

         public

           function getdat:integer;  //隱藏靜態方法

           function getage:Integer; //隱藏靜態方法

           end;

 

{ tclassa }

 

function tclassa.getage: integer;

begin

  age := 1;

  result := age;

end;

 

function tclassa.getDat: integer;

begin

  result := 3;

end;

 

{ tclassb }

 

function tclassb.getage: Integer;

begin

  Result := 1+ inherited getage();

end;

 

var a:tclassa;

   b:tclassb;

function tclassb.getdat: integer;

begin

  result := 1 + inherited getdat();

end;

 

begin

  a := tclassa.Create;

  b := tclassb.Create;

 

  Writeln(a.getage());

  Writeln(b.getage());

  Writeln(a.getdat());

  Writeln(b.getdat()); // 調用的是子類的隱藏後的靜態方法 

 

  readln;

 

  readln;

  a.free;

  b.free;

 

  { TODO -oUser -cConsole Main : Insert code here }

end.

 

我們可以看到隱藏了父類方法之後,還是可以調用父類同名方法的。這就和覆蓋是相似的。

 

 

參考資料

=================================

 

Delphi物件導向方法的分類以及覆蓋隱藏和重載

<6> 方法的分類
  按用途分 普通方法,構造方法,析構方法, 類方法,訊息處理方法
  按運行綁定機制分:靜態方法,虛方法,動態方法,[注意此處的靜態方法不是所謂的class method 而是普通的方法 ,靜態是指靜態編譯]
  關於析構方法,最好是用名字destroy ,這樣可以使用Free方法,而不要直接調用destroy方法.
  Free方法會先判斷物件變數是否為nil.
  procedure TObject.Free;
  begin
    if Self <> nil then
      Destroy;
  end;
  
  訊息處理方法的例子:
  procedure WMChar(var message:TWMChar);message WM_CHAR;
  問題來了.為什麼在一個Control中聲明了訊息處理方法,就能調用此訊息處理方法呢,這裡涉及到
  TObject 中Dispatch方法的秘密,我暫時沒有看懂.留作以後繼續學習
  先給出Dispatch的源碼.
  procedure TObject.Dispatch(var Message);
  asm
      PUSH    ESI
      MOV     SI,[EDX]
      OR      SI,SI
      JE      @@default
      CMP     SI,0C000H
      JAE     @@default
      PUSH    EAX
      MOV     EAX,[EAX]
      CALL    GetDynaMethod
      POP     EAX
      JE      @@default
      MOV     ECX,ESI
      POP     ESI
      JMP     ECX
  
  @@default:
      POP     ESI
      MOV     ECX,[EAX]
      JMP     DWORD PTR [ECX] + VMTOFFSET TObject.DefaultHandler
  end;
  
  GetDynaMethod的方法源碼如下
  procedure       GetDynaMethod;
  asm
          { ->    EAX     vmt of class            }
          {       SI      dynamic method index    }
          { <-    ESI pointer to routine  }
          {       ZF = 0 if found         }
          {       trashes: EAX, ECX               }
  
          PUSH    EDI
          XCHG    EAX,ESI
          JMP     @@haveVMT
  @@outerLoop:
          MOV     ESI,[ESI]
  @@haveVMT:
          MOV     EDI,[ESI].vmtDynamicTable
          TEST    EDI,EDI
          JE      @@parent
          MOVZX   ECX,word ptr [EDI]
          PUSH    ECX
          ADD     EDI,2
          REPNE   SCASW
          JE      @@found
          POP     ECX
  @@parent:
          MOV     ESI,[ESI].vmtParent
          TEST    ESI,ESI
          JNE     @@outerLoop
          JMP     @@exit
  
  @@found:
          POP     EAX
          ADD     EAX,EAX
          SUB     EAX,ECX         { this will always clear the Z-flag ! }
          MOV     ESI,[EDI+EAX*2-4]
  
  @@exit:
          POP     EDI
  end;
  
<7> 方法的覆蓋,隱藏和重載  
  覆蓋是override ,重載是overload;
  隱藏是子類中的方法和父類的方法同名,而且參數相同,沒有override修飾符,則子類的方法就隱藏父類的方法.
  Example:
   ...
    TChineseMan = class(TMan)
      procedure SayHello(words:string); //打招呼
    end; 
    ....
   procedure TChineseMan.SayHello(words: string);
   begin
     ShowMessage('TChinese Man SayHello '+words);
   end;
   ...
    procedure TForm1.Button1Click(Sender: TObject);
    var
     APerson:TMan;
     AChinesePerson:TChinesePerson;
    begin
     APerson:=TChineseMan.Create;
     APerson.SayHello('是一名中國人'); 
     //注意了此處調用的是父類的TMan.Sayhello方法
     //
     ChinesePerson:=TChinesePerson.Create;
     ChinesePerson.SayHello('是一名中國人'); //此時調用的是TChineseMan.sayHello
     
     //如果想要APerson調用TChineseMan.sayHello方法 應該採取強制類型轉換,強制類型轉換其實就是對象架構的範圍調整
     TChinesePerson(APerson).SayHello('是一名中國人'); //此時調用的是TChineseMan.sayHello     
    end;
    
<8>  可見度
  Delphi中四種類成員的保護方式:published,public,protected,private;   
  published,public 是可以最大訪問,protected是對之類是可見的,private是對子類不可見
  另外物件變數如果與其類的聲明在同一個單元中,則private,protected失去作用,全部都是public
  有點類似C++中友元的概念
  Example
  類TMan和此函數在同一個單元
  procedure TForm1.Button1Click(Sender: TObject);
  var
    APerson:TMan;
  begin
    TMan.Sing; 
    APerson.FAge:=10;//雖然FAge是private ,但是此處確可以訪問  
    APerson:=TMan.Create;
    APerson.Name:='小李';
    APerson.SayHello(' 是一名中國人');
  end; 

<<Delphi物件導向編程>>讀書筆記之二
<1>什麼是對象
 A.對象是一組相關代碼和資料的組合.物件導向程式設計中,過程(函數)被成為方法,資料被稱做屬性(注意此處的屬性和類中property不是一回事)
 B.對象之間可以通過發送訊息請求而互相聯絡,一個訊息通常由三部分組成:接收對象的名字,對象成員的名字(方法和property),對象成員的參數
 C.對象是有類型的,不同的對象是屬於不同的類型.

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.