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