Delphi物件模型(Part V) (轉)
模型 (PART V) :namespace prefix = o ns = "urn:schemas--com::office" />
Delphi對於物件導向的支援豐富而且強大。除了傳統的類和物件,Delphi還提供了介面,異常處理,多執行緒程式設計等特性。這一章節深入講解了Delphi的物件模型。讀者應當對標準的Pascal比較熟悉,並且對有關物件導向程式設計的基本法則有一定了解。
(本文的英文原文將Delphi與 Pascal統一表述為Delphi,可能有概念不清之嫌疑。但在大多數情況下,相信讀者能夠根據上下文來判定文中所述之Delphi的具體含義——譯者注。)
Indexed properties型的屬性
你可以將許多不同的屬性對映到一個相同的讀或寫的方法,只需為每個屬性指定一個索引值。這個索引值將被傳遞給讀或寫的方法以區別不同屬性。
你甚至可以將陣列型和索引型混合使用。讀者和寫者的方法將會區分他們——將陣列的索引作為第一個引數,接著才是索引值。
Default values預設值
屬性還用到stored和default兩個指示符。這裡的資訊與 Delphi的Object Pascal語言的特性關係不大,但是Delphi的將其用作儲存Form的描述。stored指示符的值可以是一個Boolean型別的常量,也可以是一個Boolean型的欄位,或是一個不需任何引數直接返回Boolean值方法。default指示符的值應當是與該屬性的型別相同的一個常量。只有列舉型,整形以及集合型別的屬性可以有一個預設(default)的值。stored和default指示符只對釋出的屬性才有意義。
為了將預設的陣列數型與預設的值區別開來,預設陣列的指示符以一個分號跟在屬性的宣告後面。預設值指示符則直接置於屬性宣告以後。參見第五章瞭解有關default指示符的內容。
Using properties使用屬性
通常情況下定義一個類時,我們將所有的欄位設定為私有的,然後宣告許多公開的屬性來訪問他們。然而Delphi並未對屬性直接訪問欄位方式表示不滿。但是使用屬性,你可以在未來的某個時刻改變屬性的實現,比如在欄位值發生改變是增加校驗等。你也可以使用屬性來強制訪問級別,比如當一個欄位的之不能被改變時使用一個只讀的屬性。例 2-11顯示的是宣告和使用屬性的幾種方式。
例 2-11:宣告和使用屬性
type
TCustomer = record
Name: string;
TaxIDNumber: string[9];
end;
TAccount = class
private
fCustomer: TCustomer;
fBalance: Currency;
fNumber: Cardinal;
procedure SetBalance(NewBalance: Currency);
published
property Balance: Currency read fBalance write SetBalance;
property Number: Cardinal read fNumber; //不可改變
property CustName: string read fCustomer.Name;
end;
TSavingsAccount = class(TAccount)
private
fInterestRate: Integer;
published
property InterestRate: Integer read fInterestRate
write fInterestRate default DefaultInterestRate;
end;
TLinkedAccount = class(TObject)
private
fAccounts: array[0..1] of TAccount;
function GetAccount(Index: Integer): TAccount;
public
//兩種屬性訪問陣列的方法:使用索引或者引用一個陣列元素
property Checking: TAccount index 0 read GetAccount;
property Savings: TAccount read fAccounts[1];
end;
TAccountList = class
private
fList: TList;
function GetAccount(Index: Integer): TAccount;
procedure SetAccount(Index: Integer; Account: TAccount);
function GetCount: Integer;
protected
property List: TList read fList;
public
property Count: Integer read GetCount;
property Accounts[Index: Integer]: TAccount read GetAccount
write SetAccount; default;
end;
procedure TAccount.SetBalance(NewBalance: Currency);
begin
if NewBalance < 0 then
raise EOverdrawnException.Create;
fBalance := NewBalance;
end;
function TLinkedAccount.GetAccount(Index: Integer): TAccount;
begin
Result := fAccounts[Index]
end;
function TAccountList.GetCount: Integer;
begin
Result := List.Count
end;
function TAccountList.GetAccount(Index: Integer): TAccount;
begin
Result := List[Index]
end;
procedure TAccountList.SetAccount(Index: Integer; Account: TAccount);
begin
fList[Index] := Account
end;
Class-type properties物件型別的屬性
物件型別的屬性需要引起格外的關注。使用物件型別的時候,最好由物件的擁有者負責管理物件屬性。也就是說,單單儲存一個物件引用是不夠的,需要保留一分該物件屬性的一個副本。是用一個寫者方法來做到這一點。Delphi的IDE要求所有釋出的屬性滿足這個要求,同時也對未釋出的屬性也產生影響。
此規則的唯一的例外是,屬性儲存的是對Form上的的引用。這種情況下,屬性必須儲存物件引用而非元件的副本。
Delphi的IDE只在.dfm中存放元件名稱以儲存元件引用的值。當.dfm被裝載時,Delphi查詢元件名以恢復物件引用的值。如果你必須要在一個元件內部儲存一個完整的元件,則你必須實現對內部元件的屬性的訪問委託。
確認屬性的類繼承自TPersistent而來,並且該類覆蓋了Assign方法。透過Assign來實現屬性的寫方法。(TPersistent,在Classes單元中定義,並不是必須的,但確是一個最簡單的方法——複製一個物件。否則,你將花費兩倍的代價在任何其他用到的類中書寫Assigned方法。)讀方法可以提供對欄位的直接訪問。如果該物件有一個OnChange的事件,你最好將設定其值以瞭解物件何時作了改變。例子 2-12顯示了一個典型的使用物件屬性的方法。例子中定義了一個圖形,用於在需要時在其範圍內以平鋪的方式顯示點陣圖。屬性Bitmap存放了一個TBitmap物件。
例 2-12:宣告和使用物件型別的屬性
unit Tile;
interface
uses SysUtils, Classes, Controls, Graphics;
type
// Tile a bitmap
TTile = class(TGraphicControl)
private
fBitmap: TBitmap;
procedure SetBitmap(NewBitmap: TBitmap);
procedure BitmapChanged(Sender: TObject);
protected
procedure Paint; override;
public
constructor Create(Owner: TComponent); override;
destructor Destroy; override;
published
property Align;
property Bitmap: TBitmap read fBitmap write SetBitmap;
property OnClick;
property OnlClick;
//還有許多有用的方法,限於空間不一一列出。詳見TControl。
end;
implementation
{ TTile }
// Create the bitmap when creating the control.
constructor TTile.Create(Owner: TComponent);
begin
inherited;
fBitmap := TBitmap.Create;
fBitmap.OnChange := BitmapChanged;
end;
// Free the bitmap when destroying the control.
destructor TTile.Destroy;
begin
FreeAndNil(fBitmap);
inherited;
end;
// When the bitmap changes, redraw the control.
procedure TTile.BitmapChanged(Sender: TObject);
begin
Invalidate;
end;
// Paint the control by tiling the bitmap. If there is no
// bitmap, don't paint anything.
procedure TTile.Paint;
var X, Y: Integer;
begin
if (Bitmap.Width = 0) or (Bitmap.Height = 0) then
Exit;
Y := 0;
while Y < ClientHeight do
begin
X := 0;
while X < ClientWidth do
begin
Canvas.Draw(X, Y, Bitmap);
Inc(X, Bitmap.Width);
end;
Inc(Y, Bitmap.Height);
end;
end;
//透過複製TBitmap物件的方式設定新值
procedure TTile.SetBitmap(NewBitmap: TBitmap);
begin
fBitmap.Assign(NewBitmap);
end;
end.
/develop/read_article.?id=10403">PartI
PartV
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990739/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Delphi物件模型(Part IV) (轉)物件模型
- Delphi物件模型(Part VI) (轉)物件模型
- Delphi物件模型(Part II) (轉)物件模型
- Delphi物件模型(Part III) (轉)物件模型
- Delphi中的類和物件 (轉)物件
- delphi的物件導向之路1 (轉)物件
- 擴充套件Delphi的執行緒同步物件(1) (轉)套件執行緒物件
- Delphi 中物件導向程式設計之我見 (轉)物件程式設計
- ASP.NET 頁面物件模型 (轉)ASP.NET物件模型
- 在DELPHI程式中使用ADO物件存取ODBC資料庫 (轉)物件資料庫
- Delphi與Excel (轉)Excel
- 網路IO模型-非同步選擇模型(Delphi版)模型非同步
- 在Delphi與C++之間實現函式與物件共享 (轉)C++函式物件
- 典型物件池模型的“物件過早歸還”現象分析 (轉)物件模型
- django入門-模型-part2Django模型
- C++物件模型之二 構造語句 (轉)C++物件模型
- C++物件模型之六 執行期筆記 (轉)C++物件模型筆記
- [譯] part 26: golang 的物件導向Golang物件
- 軟體測試模型-V 模型模型
- DOM 模型(文件物件模型)重點模型物件
- C++ 物件模型C++物件模型
- C++物件模型C++物件模型
- 新增模型物件操作模型物件
- XML簡明教程(4)什麼是XML物件模型(轉)XML物件模型
- C++物件導向特性實現機制的初步分析 Part3 (轉)C++物件
- C++物件導向特性實現機制的初步分析 Part1 (轉)C++物件
- Delphi 的 Utf-8 轉換
- 在DELPHI中圖片轉換
- Delphi中儲存影像列表 (轉)
- Delphi設計模式-Abstract Factory (轉)設計模式
- 用Delphi編寫DelTree程式 (轉)
- Delphi語言最佳化 (轉)
- 《delphi高手突破》節選二 (轉)
- 《delphi高手突破》節選一 (轉)
- 在Delphi中使用Queued 元件 (轉)元件
- 用DELPHI開發DirectX遊戲 (轉)遊戲
- delphi讀取ini檔案 (轉)
- Delphi中COM自動化物件中使用事件物件事件