一般我們設計一個物件,規規矩矩的從
VCL
下選擇一個最符合本身需求的物計
繼承下來,從這個物件開始擴充功能,但有時候這種標準的設計方式,有實
際的困難,一者我們手上可能沒有這個物件的
Source
,二者更改這個物件之
後,需考慮原先的物件可能已經在系統中運作,為了不破壞原有的物件功能
,及使用的介面,這個時候我們需要一種偷龍轉鳳的方法,偷偷的把這個物
件至換掉,要置換這個物件,最好的方法就是產生一個一模一樣的類別出來
,而且不改變原有物件的屬性及方法,或者是在原有物件上擴充功能。
以下提供一個另類的設計方法,來解決這個問題。假如有一個
TEdit
的物件
,我們希望它在修改資料的時候,可以改變顏色,在不改變原有物件的使用
介面下,如何來擴充這個功能呢﹖
請看這個範例的說明﹕
這個繼承自
TEdit
的
TMyEdit
很簡單的宣告
ReadOnly
這個屬性,其他
Create
,
Load
的方法,只是要在設計期間取得目前正確的顏色設定而已。
type
TMyEdit = class(TEdit)
private
FDesignColor: TColor;
FReadOnly: boolean;
procedure SetReadOnly(Value: boolean);
procedure SetColor;
protected
procedure Loaded; override;
public
constructor Create(AOwner: TComponent); override;
published
property ReadOnly: boolean read FReadOnly write SetReadOnly;
end;
接下來我們看
TMyEdit
如何改變原來的屬性,請把焦點放在
SetReadOnly
上面,這個
procedrue
動了以下的手腳
:
在繼承
ReadOnly
原有的屬性之後,進行顏色的改變。
procedure TMyEdit.SetReadOnly(Value: boolean);
begin
FReadOnly:= Value;
inherited ReadOnly:= Value;
SetColor;
end;
SetReadOnly
在父層類別
TCustomEdit
中已有定義,只是它被放在
private
區段裡,子類別是看不到的,否則只要改寫
SetReadOnly
方法就行了。在這裡重新定義了
ReadOnly
屬性,除了保有父類別
ReadOnly
屬性的作用,並賦予它新的行為。在設計類別時,也許將
Get/Set
存取方法宣告在
protected
區段會比較方便,後代類別可以直接改寫
Get/Set
方法來改變或附加行為,但這也表示父類別將失去對私有成員的保護力,子類別幾乎
可以完全改變父類別的行為。因此,要把
Get/Set
放在
private
還是
protected
區段實為見仁見智的問題,設計者可視情況選擇對自己最有利的方式。
以下是
TMyEdit
所有實作的部分﹕
constructor TMyEdit.Create(AOwner: TComponent);
begin
inherited;
FDesignColor:= clWindow;
end;
procedure TMyEdit.Loaded;
begin
inherited;
FDesignColor:= Color;
end;
procedure TMyEdit.SetColor;
begin
if ReadOnly then
Color:= clBtnFace
else
Color:= FDesignColor;
end;
procedure TMyEdit.SetReadOnly(Value: boolean);
begin
FReadOnly:= Value;
inherited ReadOnly:= Value;
SetColor;
end;
寫好這個物件我們開始進行測試,看這個物件如何無聲無息的嵌入我們已
經寫好的單元,首先我們拉一個
Form1
出來,在上面放一個
Edit1
及
Button1
,當然您還要建構這個
TMyEdit
的物件,為了方便起見,請將這
個單元直接
Copy
到
Form1
所屬的單元裡頭,然後在
Button1
上面,寫入
:
TMyEdit(Edit1).ReadOnly := False;
執行看看,按一下
Button1
,這時候
Edit1
的
ReadOnly
是不是多了改變顏色的功能﹖