文档章节

学习 TList 类的实现[8]

涂孟超
 涂孟超
发布于 2014/09/26 15:37
字数 888
阅读 2
收藏 0
点赞 0
评论 0
现在准备建立 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

共有 人打赏支持
涂孟超
粉丝 12
博文 2004
码字总数 14107
作品 0
深圳
程序员
vim for php IDE 我的打造过程

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

路边拾草人 ⋅ 2011/04/16 ⋅ 21

windows环境中vim插件配置(便利的vim)

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

_FreeDoM ⋅ 2014/06/04 ⋅ 0

[转]vim ctags使用方法

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

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

强大的vim配置文件,让编程更随意

花了很长时间整理的,感觉用起来很方便,共享一下。 我的vim配置主要有以下优点: 1.按F5可以直接编译并执行C、C++、java代码以及执行shell脚本,按“F8”可进行C、C++代码的调试 2.自动插入...

我爱吃葱花 ⋅ 2014/08/09 ⋅ 0

VIM编辑器支持Python开发环境(Vim+Ctags+Taglist)

在Linux下用VI编辑器进行Python开发,有必要对VI编辑器进行一些配置,使其具备以下特性: 1、加强的 Python 语法高亮显示; 2、对脚本、项目生成 ctag 序列; 3、在 vim 中显示 ctag 序列列表...

庄小寒 ⋅ 2014/02/26 ⋅ 0

vim中多标签和多窗口的使用

1、打开多个窗口 打开多个窗口的命令以下几个: 横向切割窗口 :new+窗口名(保存后就是文件名) :split+窗口名,也可以简写为:sp+窗口名 纵向切割窗口名 :vsplit+窗口名,也可以简写为:vsp+窗...

henry-zhang ⋅ 2015/06/09 ⋅ 0

强大的vim配置文件,让编程更随意

花了很长时间整理的,感觉用起来很方便,共享一下。 我的vim配置主要有以下优点: 1.按F5可以直接编译并执行C、C++、java代码以及执行shell脚本,按“F8”可进行C、C++代码的调试 2.自动插入...

ssiizz ⋅ 2014/08/06 ⋅ 27

强大的vim配置,让编程更随意

转自:http://blog.csdn.net/chary8088/article/details/7715383 花了很长时间整理的,感觉用起来很方便,共享一下。 我的vim配置主要有以下优点: 1.按F5可以直接编译并执行C、C++、java代码...

长平狐 ⋅ 2013/01/11 ⋅ 0

深入解析windows XP/2003:查看进程树

在windows调试工具箱中使用tilist.exe的/t开关,显示进程树。 Microsoft Windows XP [版本 5.1.2600] (C) 版权所有 1985-2001 Microsoft Corp. C:/Program Files/Debugging Tools for Windo......

晨曦之光 ⋅ 2012/03/09 ⋅ 0

vim配置经典

“在终端 输入以下命令来编辑vimrc配置文件: ”sudo vim /etc/vim/vimrc “或者 sudo gedit /etc/vim/vimrc 将其复制粘贴进去 "=========================================================...

itJackChen ⋅ 2011/08/30 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

【elasticsearch】 随笔 Date datatype

一。时间类型的本质 首先json是没有时间类型的,对于es来说,时间类型的标示可以是下面三种情况 1.一个时间格式的字符串,如:"2014-11-27T08:05:32Z","2015-01-01" or "2015/01/01 12:10:3...

xiaomin0322 ⋅ 13分钟前 ⋅ 0

阿里云资源编排ROS使用教程

阿里云资源编排ROS详细内容: 阿里云资源编排ROS使用教程 资源编排(Resource Orchestration)是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、...

mcy0425 ⋅ 15分钟前 ⋅ 0

适配器设计模式

1、适配器模式 把一个类的接口变换成客户端所期待的另一种接口 使原本因接口不匹配而无法在一起工作的两个类能够在一起工作 分为类的适配器模式和对象的适配器模式 2、类适配器模式 类的适配...

职业搬砖20年 ⋅ 19分钟前 ⋅ 0

npm操作报错 _stream_writable.js:61

有一天 不知道什么原因(估计和node的版本有关),无论你做什么npm的操作 都会报错/usr/local/lib/node_modules/npm/node_modules/readable-stream/lib/_stream_writable.js:61 这时候只要执...

lilugirl ⋅ 23分钟前 ⋅ 0

Eclipse安装插件的几种方式

Eclipse魅力之一就是支持可扩展的插件,来丰富自身的功能,这种方式也是建立在开源思想之上的。具体使用什么方式去安装插件,要看我们拿到的是什么。 1. 拿到的是一串URL,如http://subclips...

GordonNemo ⋅ 25分钟前 ⋅ 0

div图片叠加

css实现代码如下: <div style="position: relative;"><!--这个层为外面的父层,需设置相对位置样式--> <div style="position: absolute;"><!--子层,需设置绝对位置样式--> <i......

niithub ⋅ 27分钟前 ⋅ 0

作用域slot

如果父组件需要使用子组件中的内容怎么办,比如父组件需要控制子组件的显示 <div id="root"><child><template slot-scope="props"><h1>{{props.item}} <div>编辑</div></h1><......

金于虎 ⋅ 30分钟前 ⋅ 1

HongHu commonservice-eureka 项目构建过程

上一篇我们回顾了关于 spring cloud eureka的相关基础知识,现在我们针对于HongHu cloud的eureka项目做以下构建,整个构建的过程很简单,我会将每一步都构建过程记录下来,希望可以帮助到大家...

明理萝 ⋅ 32分钟前 ⋅ 1

xml和对象的相互转化

@Data//setter和getter方法,toString和equals,hashcode方法@EqualsAndHashCode//代表重写equals和hashcode方法@XmlAccessorType(XmlAccessType.FIELD)public class Classroom {@X......

拐美人 ⋅ 33分钟前 ⋅ 0

tableView cell的高度 分组头部尾部的高度 自适应

@property (nonatomic) CGFloat rowHeight; // default is UITableViewAutomaticDimension@property (nonatomic) CGFloat sectionHeaderHeight; // default is UITableViewA......

娜一片蓝色星海 ⋅ 34分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部