文档章节

学习 TList 类的实现[8]

涂孟超
 涂孟超
发布于 2014/09/26 15:37
字数 888
阅读 2
收藏 0

码上生花,ECharts 作品展示赛正式启动!>>>

现在准备建立 Items 数组属性; 在 public 区输入下面代码:
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;

 
 
 
 
 

 

 

  
至此, 我们可以使用 List.Itmes[i] 的方式访问列表中的元素了;

再进一步, 让它成为默认属性吧; 尽管只能选择一个属性为默认属性, 但哪一个属性能比它更重要的呢?
//只需把在 public 区声明的:
property Items[Index: Integer]: Pointer read GetItems write SetItems;

//改为:
property Items[Index: Integer]: Pointer read GetItems write SetItems; default;
Items 就是默认属性了, 这样再访问一个元素时, 即可以用: List.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.

 
 
 
 
 

 

 

  

本文转载自:http://www.cnblogs.com/del/archive/2008/03/31/1131210.html

涂孟超
粉丝 13
博文 2011
码字总数 14107
作品 0
深圳
程序员
私信 提问
加载中
请先登录后再评论。
看看Delphi中的列表(List)和泛型

前言 最开始学习数据结构的时候,链表,堆栈,队列,数组,似乎只是一堆概念,随着使用中慢慢接触,其对应的模型,功能,一个个跃到眼前,变成了复杂模型数据处理中的最重要的部分。---By M...

osc_x4h57ch8
2018/04/25
2
0
vim for php IDE 我的打造过程

vim是一个很强的神器,对于我只用到其中的一小部分内容,接下来是我打造 php IDE的全过程,希望有兄弟能指点我其中的不足,要学习的兄弟能跟我一起努力学习。 第一步:配_vimrc,配成自己喜欢...

路边拾草人
2011/04/16
1W
21
windows环境中vim插件配置(便利的vim)

打开vim的文件类型自动检测功能:filetype on,就是在vimrc文件中加上filetype on 1.ctags 1.1ctags功能: tags是个exe文件,在shell中执行来在工程目录中创建tags(就是函数的映射关系),适...

_FreeDoM
2014/06/04
4.4K
0
【转】vim ctag使用方法

我看到的出处没有贴来源,我转于http://www.cnblogs.com/feisky/archive/2012/02/07/2341932.html windows下很多人都使用source insight 编写和查看代码。linux下可以使用VIM,刚开始会觉得V...

osc_dk3cdlqm
2018/06/20
0
0
[转]vim ctags使用方法

windows下很多人都使用source insight 编写和查看代码。linux下可以使用VIM,刚开始会觉得VIM像windows下的记事本,而如果使用得当,它并不比source insight 逊色。 在这里,我会尽我所能细致...

文艺小青年
2017/07/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

向您推荐Groove BizTalk Workspace!

什么是Groove Office Groove 2007 是一个协作软件程序,适合用于处理从简单的文档协作到与业务过程集成的自定义解决方案的各种项目活动。 Office Groove 2007 的以下十大方式可帮助您和您的团...

osc_o8ipcpa5
23分钟前
19
0
【我的Android进阶之旅】你可能不知道android.view.View#setAlpha()方法也会影响你的APP性能!

一、问题描述 最近在优化APP的性能的时候,发现了一个平时完全没有注意到的一个能够影响APP性能的代码。这个代码就是调用了android.view.View#setAlpha()方法。 1.1 需求描述 APP有个需求,是...

osc_y08db3kb
23分钟前
21
0
lsof命令详解

lsof命令详解 lsof 简介 lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境中一切皆文件,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。所以如传输控制...

osc_htns3spg
24分钟前
14
0
设置非root账号不用sudo直接执行docker命令

环境信息 操作系统:Ubuntu 20.04 LTS 桌面版 Docker:19.03.10 现状 当前账号是willzhao,直接执行docker xxx命令会报以下错误: willzhao@ideapad:~$ docker imagesGot permission denie...

osc_kl6fknqf
25分钟前
10
0
小米净水器更换滤芯步骤和水龙头亮黄灯的解决办法

【开篇序言】 众所周知,无论何种品牌的净水器,滤芯都是有一定使用寿命的,而不是一次性安装可永久使用,如果遇到无需换滤芯这类宣布,请远离,不靠谱。换滤芯,小米净水器也不例外,小米净...

osc_zzg7fpke
26分钟前
23
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部