它可以按位儲存布爾值,因此可以看成是一個原生的Boolean值的容器類,但是它缺少列表類的很多方法和特性,不能算是一個完整的容器,因此我們稱它為擬容器類。
在我們開發過程中,經常需要表示一些類似於開關的二元狀態,這時我們用TBits來表示一組二元狀態非常方便,同時TBits類的成員函數主要是用匯編語言寫的,位操作的速度非常快。二元狀態組的大小通過設定TBits類的Size屬性來動態的調整,存取Boolean值可以通過下標來存取TBits類的Bits屬性來實現。至於OpenBit函數,它返回第一個不為True的Boolean值的下標。從接口定義可以看出,TBits類接口非常簡單,提供的功能也很有限,我猜測這只是Borland的研發隊伍滿足內部開發有限需要的類,並不是作為一個通用類來設計的,比如它沒有開放內部數據存取的接口,無法獲得內部數據的表達,進而無法實現對狀態的保存和加載等更高的需求。
TCollection類
前面我們提到了Delphi的IDE能夠自動將字符串列表保存在DFM文件中,並能在運行時將設計期編輯的字符串列表加載進內存(也就是我們通常所說的類的可持續性)。TStrings這種特性比較適合於保存一個對象同多個字符串數據之間關聯,比較類似於現實生活中一個人同多個Email賬戶地址之間的關系。但是,TStrings類型的屬性有一個很大的局限那就是,它只能用於設計時保存簡單的字符串列表,而不能保存復雜對象列表。而一個父對象同多個子對象之間的聚合關系可能更為常見,比如一列火車可能有好多節車廂構成,每節車廂都有車廂號,車廂類型(臥鋪,還是硬座),車廂座位數,車廂服務員名稱等屬性構成。如果我們想在設計期實現對火車的車廂定制的功能,並能保存車廂的各個屬性到窗體文件中,則車廂集合屬性定義為TStrings類型的屬性是行不通的。
對於這個問題,Delphi提供了TCollection容器類屬性這樣一個解決方案。TCollection以及它的容器元素TCollectionItem的接口定義如下:
TCollection = class(TPersistent)
…
protected
procedure Added(var Item: TCollectionItem); virtual; deprecated;
procedure Deleting(Item: TCollectionItem); virtual; deprecated;
property NextID: Integer read FNextID;
procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); virtual;
{ Design-time editor support }
function GetAttrCount: Integer; dynamic;
function GetAttr(Index: Integer): string; dynamic;
function GetItemAttr(Index, ItemIndex: Integer): string; dynamic;
procedure Changed;
function GetItem(Index: Integer): TCollectionItem;
procedure SetItem(Index: Integer; Value: TCollectionItem);
procedure SetItemName(Item: TCollectionItem); virtual;
procedure Update(Item: TCollectionItem); virtual;
property PropName: string read GetPropName write FPropName;
property UpdateCount: Integer read FUpdateCount;
public
constructor Create(ItemClass: TCollectionItemClass);
destructor Destroy; override;
function Owner: TPersistent;
function Add: TCollectionItem;
procedure Assign(Source: TPersistent); override;
procedure BeginUpdate; virtual;
procedure Clear;
procedure Delete(Index: Integer);
procedure EndUpdate; virtual;
function FindItemID(ID: Integer): TCollectionItem;
function GetNamePath: string; override;
function Insert(Index: Integer): TCollectionItem;
property Count: Integer read GetCount;
property ItemClass: TCollectionItemClass read FItemClass;
property Items[Index: Integer]: TCollectionItem read GetItem write SetItem;
end;
TCollectionItem = class(TPersistent)
…
protected
procedure Changed(AllItems: Boolean);
function GetOwner: TPersistent; override;
function GetDisplayName: string; virtual;
procedure SetCollection(Value: TCollection); virtual;
procedure SetIndex(Value: Integer); virtual;
procedure SetDisplayName(const Value: string); virtual;
public
constructor Create(Collection: TCollection); virtual;
destructor Destroy; override;
function GetNamePath: string; override;
property Collection: TCollection read FCollection write SetCollection;
property ID: Integer read FID;
property Index: Integer read GetIndex write SetIndex;
property DisplayName: string read GetDisplayName write SetDisplayName;
end;