Delphi學習:OOP 中的雙刃劍

前幾天看一份非常有名的商業控件的源碼,發現一個非常有趣的用法:

Integer(xxx) := aaa;

Tttt(xxx) := bbb;

細細品味,發現利用這種用法往往可以收到意想不到的效果:

比如:

TTestRec = record

A, B, C: Integer;

end;

TTestCls = class

private

FInner: TTestRec;

FReadOnlyValue: Integer;

function GetNewInner: PTestRec;

public

property Inner: TTestRec read FInner write FInner;

property NewInner: PTestRec read GetNewInner;

property ReadOnlyValue: Integer read FReadOnlyValue;

end;

你會發現,直接的你是改不了 aTestCls.Inner.A 的(編譯時 delphi 直接報錯,因爲 delphi 7 中兩個 recode 賦值是 copy memory 而不是簡單的「傳址」!

procedure TForm1.Button1Click(Sender: TObject);

begin

with TTestCls.Create do

try

// Inner.A := 10;

Caption := TButton(Sender).Caption + ' A := ' + IntToStr(Inner.A);

finally

Free;

end;

end;

可是,如果我們知道在訪問這個 Inner 時 delphi 在編譯直接 FInner 的地址,那麽,結合上面那種有趣的用法:

procedure TForm1.Button3Click(Sender: TObject);

var

p: PInteger;

begin

with TTestCls.Create do

try

p := @(Inner.A);

Integer(p^) := 100;

Caption := TButton(Sender).Caption + ' A := ' + IntToStr(Inner.A);

finally

Free;

end;

end;

更進一步,利用指針竟然可以突破 oo 對 private 的保護:

procedure TForm1.Button4Click(Sender: TObject);

var

p: PInteger;

begin

with TTestCls.Create do

try

p := @(ReadOnlyValue);

Integer(p^) := 1000;

Caption := TButton(Sender).Caption + ' ReadOnlyValue := ' + IntToStr(ReadOnlyValue);

||||||

finally

Free;

end;

end;

至于「踩過界」那更不在話下:

procedure TForm1.Button5Click(Sender: TObject);

var

p1, p2: PInteger;

begin

with TTestCls.Create do

try

p1 := @(Inner.A);

// 內存中 FInner 與 FReadOnlyValue 其實只差 TTestRec 大小個字節

Integer(p2) := Integer(p1) + SizeOf(TTestRec);

Integer(p2^) := 100;

Caption := TButton(Sender).Caption + ' ReadOnlyValue := ' + IntToStr(ReadOnlyValue);

finally

Free;

end;

end;

當然,指針不但可以破壞 oo,也能使您的代碼更加的 oo:

TTestRec = record

A, B, C: Integer;

end;

PTestRec = ^TTestRec;

TTestCls = class

private

FInner: TTestRec;

FReadOnlyValue: Integer;

function GetNewInner: PTestRec;

public

property Inner: TTestRec read FInner write FInner;

property NewInner: PTestRec read GetNewInner;

property ReadOnlyValue: Integer read FReadOnlyValue;

end;

procedure TForm1.Button2Click(Sender: TObject);

begin

with TTestCls.Create do

try

NewInner.A := 10;

Caption := TButton(Sender).Caption + ' A := ' + IntToStr(Inner.A);

finally

Free;

end;

end;

看看現實中的非 oo 的代碼:

利用「指針方案」把 Txxx 改成 Pxxx 後竟然對原來的代碼一點影響都沒有,而使之更加的 oo

 
OOP 中的雙刃劍
結論: 1、oo 是種信仰 ... 2、oo 絕對博大精深 .... ///////////////////////////////////////////////////////////////////////////////////// 前幾天看一份非常有名的商業控件的源碼,發現一個非常有趣的用法: I...查看完整版>>OOP 中的雙刃劍
 
OOP In JS [JS腳本中的面向對象]
目標讓我們輕松的實現Javascript的面向對象我們將了解在JS中如何去創建類和模塊。通過prototype來繼承.假設有兩個類: "Animal" and "Dog", Dog 從 Animal 繼承過來.Animal 類如下://constructor of Animalvar Animal...查看完整版>>OOP In JS [JS腳本中的面向對象]
 
美國媒體:戰爭中的一把“雙刃劍”
  2005年12月14日,美國總統布什在演講中承認美國出兵伊拉克的證據是錯誤的,伊戰前伊拉克並沒有大規模殺傷性武器的事實終于爲美國政府所接受。12月19日,駐伊美軍釋放了曾被美國媒體列爲撲克牌通緝令名單中的“炭...查看完整版>>美國媒體:戰爭中的一把“雙刃劍”
 
《Mastering Delphi 6》學習筆記之十一
CLX及其它 《Mastering Delphi 6》中提到Object Pascal中有一個TBits類,用來進行二進制位操作。我看過這一段之後馬上去找,果然在Classes單元中找到了它。這個類的聲明相當簡單,不過我看過後感慨很多。如果不知道這...查看完整版>>《Mastering Delphi 6》學習筆記之十一
 
簡析Delphi中的XML編程
甯波吉聯計算機技術有限公司研發部 徐榮勝 XML(eXtensible Markup Language可擴展標志語言)在近幾年的信息類雜志、網站上可謂是最搶眼的一詞。大大小小的信息産品都爭相和它搭上關系,唯恐趕不及這輛快車。有著良好...查看完整版>>簡析Delphi中的XML編程