学習TListクラスの実装[8]
5912 ワード
Items配列プロパティを作成する準備ができました.publicセクションに次のコードを入力します.
property Items[Index: Integer]: Pointer;
Shift+Ctrl+Cを実行したコードは次のとおりです.
それぞれ次のように実現されます.
さらに、デフォルトのプロパティにしましょう.デフォルトのプロパティは1つしか選択できませんが、どのプロパティがより重要ですか?
TMyListクラスの現在のすべてのコードを見てみましょう.
property Items[Index: Integer]: Pointer;
Shift+Ctrl+Cを実行したコードは次のとおりです.
...
TMyList = class(TObject)
private
...
function GetItems(Index: Integer): Pointer;
procedure SetItems(Index: Integer; const Value: Pointer);
public
...
property Items[Index: Integer]: Pointer read GetItems write SetItems;
end;
implementation
{ TMyList }
...
function TMyList.GetItems(Index: Integer): Pointer;
begin
end;
procedure TMyList.SetItems(Index: Integer; const Value: Pointer);
begin
end;
end.
TListクラスにおいてGetItemsメソッドはGetと命名される.SetItemsメソッドの名前はPut.ここでは名前を変えるつもりはありません.それぞれ次のように実現されます.
function TMyList.GetItems(Index: Integer): Pointer;
begin
if (Index < 0) or (Index >= FCount) then
raise Exception.CreateFmt(' :%d', [Index]);
Result := FList^[Index];
end;
{ , Notify , TMyList }
procedure TMyList.SetItems(Index: Integer; const Value: Pointer);
begin
if (Index < 0) or (Index >= FCount) then
raise Exception.CreateFmt(' :%d', [Index]);
if Value <> FList^[Index] then
FList^[Index] := Value;
end;
これで、リストを使用できます.Itmes[i]方式でリストの要素にアクセスしました.さらに、デフォルトのプロパティにしましょう.デフォルトのプロパティは1つしか選択できませんが、どのプロパティがより重要ですか?
// public :
property Items[Index: Integer]: Pointer read GetItems write SetItems;
// :
property Items[Index: Integer]: Pointer read GetItems write SetItems; default;
Itemsはデフォルト属性である、これにより、もう1つの要素にアクセスする場合、リストを使用することができる.Itmes[i]; 使用することもできる:List[i].デフォルトのプロパティは便利ですね.TMyListクラスの現在のすべてのコードを見てみましょう.
unit MyList;
interface
uses SysUtils;
const
MaxListSize = Maxint div 16;
type
PPointerList = ^TPointerList;
TPointerList = array[0..MaxListSize - 1] of Pointer;
TMyList = class(TObject)
private
FList: PPointerList;
FCount: Integer;
FCapacity: Integer;
procedure SetCapacity(const Value: Integer);
procedure SetCount(const Value: Integer);
function GetItems(Index: Integer): Pointer;
procedure SetItems(Index: Integer; const Value: Pointer);
public
destructor Destroy; override;
function Add(Item: Pointer): Integer;
procedure Clear;
procedure Delete(Index: Integer);
property Capacity: Integer read FCapacity write SetCapacity;
property Count: Integer read FCount write SetCount;
property List: PPointerList read FList;
property Items[Index: Integer]: Pointer read GetItems write SetItems; default;
end;
implementation
{ TMyList }
function TMyList.Add(Item: Pointer): Integer;
begin
if FCount = FCapacity then SetCapacity(FCapacity + 4);
FList^[FCount] := Item;
Result := FCount;
Inc(FCount);
end;
procedure TMyList.Clear;
begin
SetCount(0);
SetCapacity(0);
end;
procedure TMyList.Delete(Index: Integer);
begin
if (Index < 0) or (Index >= FCount) then
raise Exception.CreateFmt(' Index:%d', [Index]);
if Index < FCount then
System.Move(FList^[Index+1], FList^[Index], (FCount-Index)* SizeOf(Pointer));
Dec(FCount);
end;
destructor TMyList.Destroy;
begin
Clear;
inherited;
end;
procedure TMyList.SetCapacity(const Value: Integer);
begin
if (Value < FCount) or (Value > MaxListSize) then
raise Exception.CreateFmt(' :%d', [Value]);
if FCapacity <> Value then
begin
ReallocMem(FList, Value * SizeOf(Pointer));
FCapacity := Value;
end;
end;
procedure TMyList.SetCount(const Value: Integer);
var
i: Integer;
begin
if (Value < 0) or (Value > MaxListSize) then
raise Exception.CreateFmt(' :%d', [Value]);
if Value > FCapacity then SetCapacity(Value);
if Value > FCount then
FillChar(FList^[FCount], (Value - FCount) * SizeOf(Pointer), 0)
else
for i := FCount - 1 downto Value do
Delete(I);
FCount := Value;
end;
function TMyList.GetItems(Index: Integer): Pointer;
begin
if (Index < 0) or (Index >= FCount) then
raise Exception.CreateFmt(' :%d', [Index]);
Result := FList^[Index];
end;
procedure TMyList.SetItems(Index: Integer; const Value: Pointer);
begin
if (Index < 0) or (Index >= FCount) then
raise Exception.CreateFmt(' :%d', [Index]);
if Value <> FList^[Index] then
FList^[Index] := Value;
end;
end.
要素へのアクセスが便利になり、前のテストをやり直します.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses MyList;
type
TMyRec = record
name: string[8];
age : Word;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
ListA: TMyList;
r,r1,r2,r3,r4,r5: TMyRec;
begin
ListA := TMyList.Create;
r1.name := ' ';
r1.age := 11;
ListA.Add(@r1);
r2.name := ' ';
r2.age := 22;
ListA.Add(@r2);
r3.name := ' ';
r3.age := 33;
ListA.Add(@r3);
r4.name := ' ';
r4.age := 44;
ListA.Add(@r4);
r5.name := ' ';
r5.age := 55;
ListA.Add(@r5);
{ }
//r := TMyRec(ListA.List^[2]^); { }
r := TMyRec(ListA[2]^);
ShowMessageFmt('%s:%d',[r.name, r.age]); { :33}
{ }
ListA.Delete(2);
//r := TMyRec(ListA.List^[2]^); { }
r := TMyRec(ListA[2]^);
ShowMessageFmt('%s:%d',[r.name, r.age]); { :44}
{ Items , , }
ListA[2] := @r1;
r := TMyRec(ListA[2]^);
ShowMessageFmt('%s:%d',[r.name, r.age]); { :11}
ListA.Free;
end;
end.