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

Delphi中靜態方法重載仍是覆蓋的討論編程

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

 

答案是隱藏父類方法。ide

 

通常咱們的理解重載是同名,不一樣參數的同一個類裏面實現,函數

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

 

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

 

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

 

不然同名,同參數就是隱藏方法。spa

=================================================================設計

下面是筆者本身的程序,您能夠嘗試一下。code

 

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.對象是有類型的,不一樣的對象是屬於不一樣的類型.

相關文章
相關標籤/搜索