学习 TList 类的实现[4]

现在准备一步步地模拟 TList 类, 建立一个自己的 TMyList.

首先, 这个类中应该包括前面提到的那个 Pointer 数组(TPointerList)的指针(PPointerList):

TMyList = class(TObject)

  FList: PPointerList;

end;


 
   
既然是一个列表, 应该有 Count 字段:

TMyList = class(TObject)

  FList: PPointerList;

  FCount: Integer;

end;


 
   
TList 类还有一个 FCapacity 字段.

譬如当前列表中有 10 个元素时, 其实列表已经提前申请出更多位置, 这样就不必每次添加每次申请内存, 从而提高了效率.

这个 FCapacity 字段就表示已申请的可放置元素位置的总数.

TMyList = class(TObject)

  FList: PPointerList;

  FCount: Integer;

  FCapacity: Integer;

end;


 
   
它们都应该是私有的:

TMyList = class(TObject)

private

  FList: PPointerList;

  FCount: Integer;

  FCapacity: Integer;

public

end;


 
   
应该用属性操作它们:

unit Unit1;



interface



uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs;



type

  TForm1 = class(TForm)

  end;

{--------------------------------}

  TMyList = class(TObject)

  private

    FList: PPointerList;

    FCount: Integer;

    FCapacity: Integer;

  public

    property Capacity: Integer; {光标放在属性上, 执行 Shift+Ctrl+C, 自动建立属性}

    property Count: Integer;

    property List: PPointerList;

  end;

{--------------------------------}



var

  Form1: TForm1;



implementation



{$R *.dfm}



end.


 
   
自动建立后的属性:

unit Unit1;



interface



uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs;



type

  TForm1 = class(TForm)

  end;

{--------------------------------}

  TMyList = class(TObject)

  private

    FList: PPointerList;

    FCount: Integer;

    FCapacity: Integer;

    procedure SetCapacity(const Value: Integer);

    procedure SetCount(const Value: Integer);

    procedure SetList(const Value: PPointerList);

  public

    property Capacity: Integer read FCapacity write SetCapacity;

    property Count: Integer read FCount write SetCount;

    property List: PPointerList read FList write SetList;

  end;

{--------------------------------}



var

  Form1: TForm1;



implementation



{$R *.dfm}



{ TMyList }



procedure TMyList.SetCapacity(const Value: Integer);

begin

  FCapacity := Value;

end;



procedure TMyList.SetCount(const Value: Integer);

begin

  FCount := Value;

end;



procedure TMyList.SetList(const Value: PPointerList);

begin

  FList := Value;

end;



end.


 
   
在 TList 中, SetCount 和 SetCapacity 方法都是放在 protected 区以供子类使用, 这里暂时不考虑继承的问题, 就让它们先在 private 区吧;

不过 List 属性应该是只读的, 它就是那个核心数组的指针, 对它的赋值应该通过更多其他的方法.

修改如下:

unit Unit1;



interface



uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs;



type

  TForm1 = class(TForm)

  end;

{--------------------------------}

  TMyList = class(TObject)

  private

    FList: PPointerList;

    FCount: Integer;

    FCapacity: Integer;

    procedure SetCapacity(const Value: Integer);

    procedure SetCount(const Value: Integer);

  public

    property Capacity: Integer read FCapacity write SetCapacity;

    property Count: Integer read FCount write SetCount;

    property List: PPointerList read FList;

  end;

{--------------------------------}



var

  Form1: TForm1;



implementation



{$R *.dfm}



{ TMyList }



procedure TMyList.SetCapacity(const Value: Integer);

begin

  FCapacity := Value;

end;



procedure TMyList.SetCount(const Value: Integer);

begin

  FCount := Value;

end;



end.


 
   
作为一个列表, 最起码应该有 Add、Delete、Clear 方法.

Add 方法的参数应该是一个指针(TList 就是存放指针的吗), 如果需要同时返回元素的位置, 应该定义成函数;

Delete 是删除指定位置上的元素, 参数是个位置号;

Clear 是清除列表, 对象释放(Destroy)时也应该执行此过程.

综上所述, 修改如下:

unit Unit1;



interface



uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs;



type

  TForm1 = class(TForm)

  end;

{--------------------------------}

  TMyList = class(TObject)

  private

    FList: PPointerList;

    FCount: Integer;

    FCapacity: Integer;

    procedure SetCapacity(const Value: Integer);

    procedure SetCount(const Value: Integer);

  public

    destructor Destroy; override;         {覆盖父类的 Destroy 方法}

    function Add(Item: Pointer): Integer;

    procedure Clear;                      {在 TList 中这是个虚方法, 以备子类覆盖}

    procedure Delete(Index: Integer);

    property Capacity: Integer read FCapacity write SetCapacity;

    property Count: Integer read FCount write SetCount;

    property List: PPointerList read FList;

  end;

{--------------------------------}



var

  Form1: TForm1;



implementation



{$R *.dfm}



{ TMyList }



function TMyList.Add(Item: Pointer): Integer;

begin



end;



procedure TMyList.Clear;

begin



end;



procedure TMyList.Delete(Index: Integer);

begin



end;



destructor TMyList.Destroy;

begin

  Clear;     {在类释放时同时清除列表}

  inherited; {在 TList 中没有这句, 大概是因为它的父类也没什么可继承的}

end;



procedure TMyList.SetCapacity(const Value: Integer);

begin

  FCapacity := Value;

end;



procedure TMyList.SetCount(const Value: Integer);

begin

  FCount := Value;

end;



end.


 
   
为了让代码更清晰, 还是把这个类相关的所有代码放到一个独立的单元吧(新建一个单元, 我们把它保存为: MyList.pas).

因为 MaxListSize、TPointerList、PPointerList 都是在 Classes 单元定义的, 为了省略 uses Classes, 在 MyList 单元中重新做了定义.

unit MyList;



interface



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);

  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;

  end;



implementation



{ TMyList }



function TMyList.Add(Item: Pointer): Integer;

begin



end;



procedure TMyList.Clear;

begin



end;



procedure TMyList.Delete(Index: Integer);

begin



end;



destructor TMyList.Destroy;

begin

  Clear;

  inherited;

end;



procedure TMyList.SetCapacity(const Value: Integer);

begin



end;



procedure TMyList.SetCount(const Value: Integer);

begin



end;



end.


 
   
至此, 类的轮廓已经出来, 该实现一下这些方法了.

你可能感兴趣的:(list)