博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习 TList 类的实现[4]
阅读量:5814 次
发布时间:2019-06-18

本文共 5624 字,大约阅读时间需要 18 分钟。

  hot3.png

现在准备一步步地模拟 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;publicend;
应该用属性操作它们:

unit Unit1;interfaceuses  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;interfaceuses  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;interfaceuses  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;interfaceuses  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;beginend;procedure TMyList.Clear;beginend;procedure TMyList.Delete(Index: Integer);beginend;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;interfaceconst  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;beginend;procedure TMyList.Clear;beginend;procedure TMyList.Delete(Index: Integer);beginend;destructor TMyList.Destroy;begin  Clear;  inherited;end;procedure TMyList.SetCapacity(const Value: Integer);beginend;procedure TMyList.SetCount(const Value: Integer);beginend;end.
至此, 类的轮廓已经出来, 该实现一下这些方法了.

转载于:https://my.oschina.net/hermer/blog/320057

你可能感兴趣的文章
项目笔记:测试类的编写
查看>>
通过容器编排和服务网格来改进Java微服务的可测性
查看>>
re:Invent解读:没想到你是这样的AWS
查看>>
PyTips 0x02 - Python 中的函数式编程
查看>>
阿里云安全肖力:安全基础建设是企业数字化转型的基石 ...
查看>>
使用《Deep Image Prior》来做图像复原
查看>>
如何用纯 CSS 为母亲节创作一颗像素画风格的爱心
查看>>
Linux基础命令---rmdir
查看>>
iOS sqlite3(数据库)
查看>>
粤出"飞龙",打造新制造广东样本
查看>>
编玩边学获数千万元A轮融资,投资方为君联资本
查看>>
蓝图(Blueprint)详解
查看>>
Spark之SQL解析(源码阅读十)
查看>>
Android图片添加水印图片并把图片保存到文件存储
查看>>
比特币系统采用的公钥密码学方案和ECDSA签名算法介绍——第二部分:代码实现(C语言)...
查看>>
海贼王十大悲催人物
查看>>
BigDecimal 舍入模式(Rounding mode)介绍
查看>>
开源 免费 java CMS - FreeCMS1.2-标签 infoSign
查看>>
开源 免费 java CMS - FreeCMS1.9 移动APP生成栏目列表数据
查看>>
git reset 三种用法总结
查看>>