Delphi中的容器类_陈省
- 格式:doc
- 大小:68.00 KB
- 文档页数:18
delphi⽂件后缀全解delphi⽂件后缀全解1. 项⽬⽂件(.dpr):Delphi项⽬⽂件,⽤于保存窗体、单元等的信息,以及程序运⾏的初始化代码等,这种⽂件实际上包含了Pascal源代码。
2. 单元⽂件(.pas):Pascal⽂件,⽤于保存程序源代码,可以是与窗体有关的单元或是独⽴的单元。
3. 窗体⽂件(.dfm):保存窗体或数据模块及其构件特性的⼆进制⽂件。
4. 选项⽂件(.dof):含有当前项⽬选项设置的⽂本⽂件。
5. Package源⽂件(.dpk):软件包的项⽬源代码⽂件,⽤于管理Packages信息。
6. 资源⽂件(.res):该⼆进制⽂件包含项⽬的图标,由Delphi不断更新和创建,⽤户⼀般不需要修改。
7. 备份⽂件(.-dp,.-df,-pa):分别对应项⽬、窗体、单元⽂件的备份⽂件。
8. Desktop⽂件(.dsk):包含了与Delphi窗⼝的位置、在编辑器中打开的⽂件及其它桌⾯设置有关的信息。
9. 类型库(.tlb):⼀种⾃动建⽴或由类型库编辑器为OLE服务器端应⽤程序建⽴的。
10. 项⽬配置⽂件(.cfg):保存项⽬配置,⽂件名与项⽬名相同,但后缀为.CFG。
11. Code Insight配置⽂件(.dcl):保存IDE中对Code Insight的修改信息。
12. 构件板配置⽂件(.dct):保存IDE中对构件板的修改信息。
13. 菜单配置⽂件(. dmt):保存IDE中对Delphi菜单的修改信息。
14. 容器库修改⽂件(. dmt):保存程序对Delphi菜单容器库的修改信息。
15. ⾏为列表⽂件(.todo):保存当前项⽬的⾏为列表。
⽂件名与项⽬名相同,但后缀为.todo。
下⾯是程序编译后,Delphi⾃动创建的⽂件:1. 执⾏⽂件(.exe):为程序编译后的Windows执⾏⽂件。
2. 单元对象⽂件(.dcu):是单元⽂件的编译版本,会连接到最终的执⾏⽂件中。
Delphi中Frame的使⽤⽅法Frame是组件⾯板上的第⼀个组件,但不是每个⼈都知道怎么⽤它,因为它不像Button和Label ⼀样简单明了。
实际上,Frame按钮只是打开⼀个Frame的列表,如果你没有创建任何的Frame,⾃然什么也不会看到。
那么Frame到底是什么呢?简单来说:1. Frame是组件容器,类似Panel2. Frame在使⽤上类似Components组件,但并没有构造器和解析器,依赖于⽗容器完成Destroy的⼯作3. Frame可以继承和嵌套4. Frame内部的控件都是公开的,可以在IDE⾥重置属性和事件,所以frame的内部封装⼀般都是松散的。
访问frame上的组件⽤frame.control⽅式5. Frame的使⽤范围仅在当前⼯程内6. Frame的使⽤不像⼀般组件component有独⽴的功能,很多时候需要和⽗容器耦合在⼀起看了半天还是不明⽩?看个例⼦吧:上图是⼀个客户信息的Frame,因为在客户信息在很多的地⽅都需要显⽰,并且带编辑,查询,发邮件等按钮。
当然你可以每次⽤到都拷贝⼀遍,但是做成frame组件,⽤的时候只要告诉frame客户id,剩下都交由组件本⾝完成,岂不是⽅便很多?所以,frame和普通components组件⼀样,都是为复⽤设计的。
只是frame是Delphi的特技,是⼀种简化版组件。
如果你有⼀组可视化组件的集合,在多个地⽅重复出现,就应该考虑使⽤Frame了。
如何创建⼀个Frame呢,如图:你可以把frame添加到组件⾯板,如图:Frame在写代码时和⼀般组件有什么不同呢?⽐如(1)中的客户信息的frame,如果想重写客户编辑按钮的click事件,会发⽣什么呢:procedure TBusOnSiteManager.FrameCustomerButtonEditCustomerClick(Sender: TObject); begininherited;FrameCustomer.ButtonEditCustomerClick(Sender);end;可见,IDE会⾃动加上调⽤Frame中按钮click的⽅法,当然,你可以注释掉它,写上⾃⼰的代码。
Delphi 程序设计基础教程第 1 章Delphi 集成开发环境1. 填空题(1) Delphi 是一个集成开发环境,从 3程序设计、代码编译、调试,到最布程序的全部工作都可以在这个集成环境中完成。
(2) 在 Delphi 集成环境的主要组成部分中有许多功能强大的工具,如: 3主窗体、对象树状视图、对象观察器、窗体设计器、代码编辑器工具等。
(3) Delphi 集成开发环境的界面分为4个部分,分别是。
主窗口、窗体窗口、代码编辑窗口和对象查看器窗口(4) 对象查看器的功能是:编辑设置窗体、组件的属性,并为窗体、组件添加事件的响应处理过程(5) Delphi 主窗口由:标题栏、菜单栏、工具栏和组件板组成,它是打开其他窗口和退出D elphi 集成环境的主要界面。
2. 选择题D(1) 对象查看器由组成。
A. 标题栏、菜单栏、属性标签和事件标签B. 标题栏、菜单栏、对象选择器和事件标签C. 标题栏、菜单栏、对象选择器和属性标签D. 标题栏、对象选择器、属性标签和事件标签D(2) Delphi 用来管理用户开发的应用程序中的各个文件,有序地管理可以极大地提高应用程序开发的质量和速度。
A. 单元B. 组件C. 属性D. 项目B(3) 用来编写应用程序的代码。
A. 调试器窗口B. 代码编辑窗口C. 报表生成器窗口D. 数据库桌面窗口B(4) 代码编辑窗口分为左、右两部分:。
A. 左边是单元代码窗口,右边是单元浏览器窗口B. 左边是单元浏览器窗口,右边是单元代码窗口C. 左边是单元调试窗口,右边是单元浏览器窗口D. 左边是单元浏览器窗口,右边是单元调试窗口A(5) 属性选项卡即标签名为“Properties”的选项卡,用于设置当前组件的属性,属性选项卡是一个两列的表格,。
A. 左列是属性标题,右列是属性值B. 左列是组件名称,右列是事件名C. 左列是属性标题,右列是事件名D. 左列是组件名称,右列是属性值C(6) 事件选项卡即标签名为“Events”的选项卡,用于为当前组件添加各种响应事件(如单击、拖曳事件等),它随对象选择器中的所选组件而发生变化。
Delphi操作ACCESS技巧集1.DELPHI中操作access数据库(建⽴.mdb⽂件,压缩数据库)以下代码在WIN2K,D6,MDAC2.6下测试通过,编译好的程序在WIN98第⼆版⽆ACCESS环境下运⾏成功.//在之前uses ComObj,ActiveX//声明连接字符串ConstSConnectionString = 'PRovider=Microsoft.Jet.OLEDB.4.0;Data Source=%s;'+'Jet OLEDB:Database PassWord=%s;';//=============================================================================// Procedure: GetTempPathFileName// Author : ysai// Date : 2003-01-27// Arguments: (None)// Result : string//=============================================================================function GetTempPathFileName():string;//取得临时⽂件名varSPath,SFile:array [0..254] of char;beginGetTempPath(254,SPath);GetTempFileName(SPath,'~SM',0,SFile);result:=SFile;DeleteFile(PChar(result));end;//=============================================================================// Procedure: CreateAccessFile// Author : ysai// Date : 2003-01-27// Arguments: FileName:String;PassWord:string=''// Result : boolean//=============================================================================function CreateAccessFile(FileName:String;PassWord:string=''):boolean;//建⽴Access⽂件,如果⽂件存在则失败varSTempFileName:string;vCatalog:OleVariant;beginSTempFileName:=GetTempPathFileName;tryvCatalog:=CreateOleObject('ADOX.Catalog');vCatalog.Create(format(SConnectionString,[STempFileName,PassWord]));result:=CopyFile(PChar(STempFileName),PChar(FileName),True);DeleteFile(STempFileName);exceptresult:=false;end;end;//=============================================================================// Procedure: CompactDatabase// Author : ysai// Date : 2003-01-27// Arguments: AFileName,APassWord:string// Result : boolean//=============================================================================function CompactDatabase(AFileName,APassWord:string):boolean;//压缩与修复数据库,覆盖源⽂件varSTempFileName:string;vJE:OleVariant;beginSTempFileName:=GetTempPathFileName;tryvJE:=CreateOleObject('JRO.JetEngine');pactDatabase(format(SConnectionString,[AFileName,APassWord]),format(SConnectionString,[STempFileName,APassWord]));result:=CopyFile(PChar(STempFileName),PChar(AFileName),false);DeleteFile(STempFileName);exceptresult:=false;end;end;//=============================================================================// Procedure: ChangeDatabasePassword// Author : ysai// Date : 2003-01-27// Arguments: AFileName,AOldPassWord,ANewPassWord:string// Result : boolean//=============================================================================function ChangeDatabasePassword(AFileName,AOldPassWord,ANewPassWord:string):boolean;//修改ACCESS数据库密码varSTempFileName:string;vJE:OleVariant;beginSTempFileName:=GetTempPathFileName;tryvJE:=CreateOleObject('JRO.JetEngine');pactDatabase(format(SConnectionString,[AFileName,AOldPassWord]),format(SConnectionString,[STempFileName,ANewPassWord]));result:=CopyFile(PChar(STempFileName),PChar(AFileName),false);DeleteFile(STempFileName);exceptend;end;2.ACCESS中使⽤SQL语句应注意的地⽅及⼏点技巧以下SQL语句在ACCESS XP的查询中测试通过建表:Create Table Tab1 (ID Counter,Name string,Age integer,[Date] DateTime);技巧:⾃增字段⽤ Counter 声明.字段名为关键字的字段⽤⽅括号[]括起来,数字作为字段名也可⾏.建⽴索引:下⾯的语句在Tab1的Date列上建⽴可重复索引Create Index iDate ON Tab1 ([Date]);完成后ACCESS中字段Date索引属性显⽰为 - 有(有重复).下⾯的语句在Tab1的Name列上建⽴不可重复索引Create Unique Index iName ON Tab1 (Name);完成后ACCESS中字段Name索引属性显⽰为 - 有(⽆重复).下⾯的语句删除刚才建⽴的两个索引Drop Index iDate ON Tab1;Drop Index iName ON Tab1;ACCESS与SQLSERVER中的UPDATE语句对⽐:SQLSERVER中更新多表的UPDATE语句:UPDATE Tab1SET = FROM Tab1 a,Tab2 bWHERE a.ID = b.ID;同样功能的SQL语句在ACCESS中应该是UPDATE Tab1 a,Tab2 bSET = WHERE a.ID = b.ID;即:ACCESS中的UPDATE语句没有FROM⼦句,所有引⽤的表都列在UPDATE关键字后.上例中如果Tab2可以不是⼀个表,⽽是⼀个查询,例:UPDATE Tab1 a,(Select ID,Name From Tab2) bSET = WHERE a.ID = b.ID;访问多个不同的ACCESS数据库-在SQL中使⽤In⼦句:Select a.*,b.* From Tab1 a,Tab2 b In 'db2.mdb' Where a.ID=b.ID;上⾯的SQL语句查询出当前数据库中Tab1和db2.mdb(当前⽂件夹中)中Tab2以ID为关联的所有记录.缺点-外部数据库不能带密码.补充:看到ugvanxk在⼀贴中的答复,可以⽤Select * from [c:\aa\a.mdb;pwd=1111].table1;ACCESS XP测试通过ACCESS⽀持⼦查询ACCESS⽀持外连接,但不包括完整外部联接,如⽀持LEFT JOIN 或 RIGHT JOIN但不⽀持FULL OUTER JOIN 或 FULL JOINACCESS中的⽇期查询注意:ACCESS中的⽇期时间分隔符是#⽽不是引号Select * From Tab1 Where [Date]>#2002-1-1#;在DELPHI中我这样⽤SQL.Add(Format('Select * From Tab1 Where [Date]>#%s#;',[DateToStr(Date)]));ACCESS中的字符串可以⽤双引号分隔,但SQLSERVER不认,所以为了迁移⽅便和兼容,建议⽤单引号作为字符串分隔符.delphi读取⼀个ACCESS数据库中的表名ADOConnection1.Close;ADOConnection1.ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source='+ Edit1.Text + ';Persist Security Info=False';ADOConnection1.Open;ADOConnection1.GetTableNames(ComboBox1.Items);ComboBox1.ItemIndex := 0;View Codedelphi和access连接的⽅式1.SQL数据库的联接⽅式:条件:控件名:AdoConnecion1,数据库名:Sample,⽤户名:sa 密码:123,数据库地址:本机AdoConnection1.ConnectionString:='Provider=SQLOLEDB.1;Password=123;Persist Security Info=True;User ID=sa;Initial Catalog=Sample;Data Source=.'; Adoconnection1.LoginPrompt:=False;Adoconnection1.Connected:=True;上⾯这段代码为SQL数据库的联接⽅式:最后⼀句Data Source=. 其中的“.”表⽰为数据库在本机,如果数据在其它地⽅,则将点改为IP地址或是服务器名称。
Delphi中的动态数组总结今天做的⼀个项⽬中要使⽤⼀⼤串数据进⾏处理。
如何对这⼀系列的数据进⾏保存成为⼀个⾸要的问题。
唉,Delphi啊,你何时才能⽀持泛型啊。
在C#,C++这都不是问题了啊。
在Delphi⾥只有TStringList这个容器可以使⽤,但是它是处理字符串的。
⼀进⼀出,需要⼤量的typecast时间。
⽤链表??不值得。
上⽹⼀查,呵呵,可以⽤动态数组。
看来我还是⼀个新⼿,这个东西我都不知道啊。
啥时候Delphi有了这个玩意了。
vari:array of integer;beginSetLength(i,length);//设置动态数组的长度以后就可以像正常数组那样操作有了动态数组就可以随时设置数组的⼤⼩,不会像以前那样事先定义数组的⼤⼩,对资源造成浪费。
动态数组的本质还是指针,上⾯的例⼦。
i 就是⼀个指针类型。
可以将两个动态数组之间进⾏引⽤赋值,当然了我们也可以将其复制给⼀个Pointer,只不过意义不⼤罢了。
varp:Pointer;i,j:Array of integer;beginSetLength(i,20);//分配内存空间i[0] := 22;i := j;//此时,i,j都同时指向了那段动态数组的存p := i; //没有实际意义,只是证明了i 是指针类型//释放⼯作end;使⽤完了内存当然需要释放了,否则会造成内存泄露。
动态数组使⽤了 reference-counting 技术,所以在使⽤完后,只需将其赋值为nil即可。
-------------------------------------------------------------------⾃从有了动态数组,链表除了在教科书⾥出现外,已经很少在实际编程中被使⽤了,事实也是如此,数组的确⽐传统链表快得多,⽽且也⽅便的多。
从 Delphi4起,开始了内建各种类型的动态数组⽀持。
但是,对我们来说动态数组⽀持似乎做的不够彻底,因为Delphi竟然连删除、插⼊、移动连续元素的函数都没有提供,让⼈使⽤起来总觉得不够爽!!! J 。
Delphi-基础(常量、集合、数组[动态数组、多维数组])⼀、常量 1、常量定义:⼀开始定义好的值,以后在程序的运⾏过程中不允许改变1const2 Pi : Double = 3.141592; //定义为常量3{常量的定义⽅式,可以不进⾏类型的声明,编译器会根据具体值决定常量的的类型}4 Pi2 = 3.1415;2、常量使⽤ 枚举:常量集 type 枚举名=(标识符1,标识符2,标识符3,......)1type2{正常情况下,枚举类型的索引是从0开始}3 EColors = (RED,GREEN,BLUE);4 EWeek = (SUN=7,MON=1,TUE=2,WED=3,THU=4,FRI=5,SAT=6);5var6 Color : EColors;7 Week : EWeek;89begin10 Color := EColors.RED;11 Week := EWeek.SUN;12 Writeln(Ord(Color),',',Ord(Week));13 REDln;14end.⼆、⼦界 使⽤:为了防治出现越界 注意事项: 1、⼦界要求上界和下界必须是有序的数据类型整数、字符、枚举 2、⼦界的上界⼤于或者等于下界 格式:type ⼦界1{定义格式}2type3{枚举}4 EColors = (RED,GREEN,BLUE);5{⼦界}6 TSubBoundNumber = 1..10;7 TSubBoundChar = 'a'..'z';8910begin11 Writeln(Low(TSubBoundNumber)); //下界12 Writeln(High(TSubBoundChar)); //上界13 REDln;14end.打印出闰年还是平年,每个⽉的天数和所属季节1{打印出闰年还是平年,每个⽉的天数和所属季节}2type3{⼦界}4 TSubBoundMonths = 1..12;5{枚举}6 ESeason = (Spring,Summer,Autumn,Winter);78var9 Season : ESeason;1415procedure SubBound();16begin17 Writeln('请输⼊⼀个年份:');18 REDln(User_Year);19{默认为闰年}20 Is_Leap_Year := True;21while Is_Leap_Year do22begin23if (User_Year mod4) = 0then begin24if not((User_Year mod100) = 0) then begin25 Writeln('闰年',User_Year);26 Is_Leap_Year := False;27end;28end;29if (User_Year mod400) = 0then begin30 Writeln('闰年',User_Year);31 Is_Leap_Year := False;32end33else begin34 Is_Leap_Year := False;35 Writeln('平年',User_Year)3637end;38end;3940end;41procedure Months();42begin43{季节}44 Writeln('请输⼊⼀个⽉份:');45 REDln(User_Month);46begin47if (User_Month >= Low(TSubBoundMonths)) and (User_Month <= High(TSubBoundMonths)) then48if (User_Month >= 1) and (User_Month <= 3) then begin49 Writeln('当前季节为春季');50case User_Month of511 : begin52 Writeln('31天');53end;542 : begin55if Is_Leap_Year then begin56 Writeln('29天');57end else begin58 Writeln('28天');59end;60end;613 : begin62 Writeln('31天');63end;64end;65end;6667end;68end;6970begin71// Writeln(Low(TSubBoundNumber)); //下界72// Writeln(High(TSubBoundChar)); //上界7374 SubBound();75 Months();76 REDln;77end.View Code三、集合集合是由具有某些共同特征的元素结构的⼀个整体。
Delphi历史版本详解-从Turbo Pascal 到Delphi XE 2delphi每每升级都在继续完善扩展面向对象的特性,这是升级新版本的最重要的原因。
大略说下语言层面上的变化。
d2005开始支持记录的运算符重载特性,运算符重载在需要大量数学运算编码时尤为方便。
等等。
d2007加入了对触屏的支持,vcl内不少数据组件进行了更新。
等等。
d2009开始全面支持unicode,并开始加入泛型,新增了一些泛型容器。
有了泛型delphi终于才能说是个完整的面向对象语言。
再一个开始对vista\win7的新winapi的支持。
等等。
d2010开始继续完善上个版本中的泛型特性,并扩充和再次新增了一些泛型类。
xe变化不大,只是继续对vcl修修补补,记得新增了delphi 的原生的正则支持,加入的那个正则类叫啥名字也记不清了,反正不需要再用第三方的正则库了。
等等。
x2变动挺大,把winapi进行了重新封装。
加入了firemonkey框架、支持win64位编译,号称跨平台。
在gdi+出现的10年后终于gdi+封装进了vcl,可直接使用gdi+这个快淘汰的东东了。
等等。
xe3 继续号称跨平台,win64位编译。
继续修修补补。
等等LX补充。
个人推荐D2009和xe。
另外高版本中强化的调试功能和单元测试等等这些是d7没法比拟的,这也是升级高版本的重要原因。
我是同时装有d7、d2009和xe。
写些只需三两千或几百行的玩具应用用d7就好,编译的exe也精悍。
干活时都是d2009或xe,xe用得较多。
-------------------------------------------------------------------------------------------------------------------------------------------Delphi历史版本详解-从Turbo Pascal 到Delphi XE 2 日期:2011年9月9日在delphi XE2发布之际,满足各位D迷得要求,跟大家分享一下从Turbo Pascal 到Delphi XE 2 各个版本历史。
Delphi中的容器类作者陈省从Delphi 5开始VCL中增加了一个新的Contnrs单元,单元中定义了8个新的类,全部都是基于标准的TList 类。
TList 类TList 类实际上就是一个可以存储指针的容器类,提供了一系列的方法和属性来添加,删除,重排,定位,存取和排序容器中的类,它是基于数组的机制来实现的容器,比较类似于C++中的Vector和Java中的ArrayList,TList 经常用来保存一组对象列表,基于数组实现的机制使得用下标存取容器中的对象非常快,但是随着容器中的对象的增多,插入和删除对象速度会直线下降,因此不适合频繁添加和删除对象的应用场景。
下面是TList类的属性和方法说明:属性描述Count: Integer;返回列表中的项目数Items[Index: Integer]: Pointer; default通过以0为底的索引下标直接存取列表中的项目方法类型描述Add(Item: Pointer): Integer;函数用来向列表中添加指针Clear;过程清空列表中的项目Delete(Index: Integer);过程删除列表中对应索引的项目IndexOf(Item: Pointer): Integer;函数返回指针在列表中的索引Insert(Index: Integer; Item: Pointer);过程将一个项目插入到列表中的指定位置Remove(Item: Pointer): Integer;函数从列表中删除指针名称类型描述Capacity: Integer;property可以用来获取或设定列表可以容纳的指针数目Extract(Item: Pointer): Pointer;functionExtract 类似于Remove 可以将指针从列表中删除,不同的是返回被删除的指针。
Exchange(Index1, Index2: Integer);procedure交换列表中两个指针First: Pointer;function返回链表中的第一个指针Last: Pointer;function返回链表中最后一个指针Move(CurIndex NewIndex: Integer);procedure将指针从当前位置移动到新的位置Pack;procedure从列表中删除所有nil指针Sort(Compare: TListSortCompare);procedure用来对链表中的项目进行排序,可以设定Compare参数为用户定制的排序函数TObjectList 类TObjectList 类直接从TList 类继承,可以作为对象的容器。
TObjectList类定义如下:TObjectList = class(TList)...publicconstructor Create; overload;constructor Create(AOwnsObjects: Boolean); overload;function Add(AObject: TObject): Integer;function Remove(AObject: TObject): Integer;function IndexOf(AObject: TObject): Integer;function FindInstanceOf(AClass: TClass;AExact: Boolean = True; AStartAt: Integer = 0):Integer;procedure Insert(Index: Integer; AObject: TObject);property OwnsObjects: Boolean;property Items[Index: Integer]: TObject; default;end;不同于TList类,TObjectList类的Add, Remove, IndexOf, Insert等方法都需要传递TObject对象作为参数,由于有了编译期的强类型检查,使得TObjectList比TList更适合保存对象。
此外TObjectList对象有OwnsObjects属性。
当设定为True (默认值),同TList类不同,TObjectList对象将销毁任何从列表中删除的对象。
无论是调用Delete, Remove, Clear 方法,还是释放TObjectList对象,都将销毁列表中的对象。
有了TObjectList类,我们就再也不用使用循环来释放了对象。
这就避免了释放链表对象时,由于忘记释放链表中的对象而导致的内存泄漏。
另外要注意的是OwnsObjects属性不会影响到Extract方法,TObjectList的Extract方法行为类似于TList,只是从列表中移除对象引用,而不会销毁对象。
TObjectList 对象还提供了一个FindInstanceOf 函数,可以返回只有指定对象类型的对象实例在列表中的索引。
如果AExact 参数为True,只有指定对象类型的对象实例会被定位,如果AExact 对象为False,AClass 的子类实例也将被定位。
AStartAt 参数可以用来找到列表中的多个实例,只要每次调用FindInstanceOf 函数时,将起始索引加1,就可以定位到下一个对象,直到FindInstanceOf 返回-1。
下面是代码示意:varidx: Integer;beginidx := -1;repeatidx := ObjList.FindInstanceOf(TMyObject, True, idx+1);if idx >= 0 then...until(idx < 0);end;TComponentList 类Contnrs单元中还定义了TComponentList 类,类定义如下:TComponentList = class(TObjectList)...publicfunction Add(AComponent: TComponent): Integer;function Remove(AComponent: TComponent): Integer;function IndexOf(AComponent: TComponent): Integer;procedure Insert(Index: Integer; AComponent: TComponent);property Items[Index: Integer]: TComponent; default;end;注意TComponentList 是从TObjectList类继承出来的,它的Add, Remove, IndexOf, Insert和Items 方法调用都使用TComponent 类型的参数而不再是TObject类型,因此适合作为TComponent对象的容器。
TComponentList 类还有一个特殊的特性,就是如果链表中的一个组件被释放的话,它将被自动的从TComponentList 链表中删除。
这是利用TComponent的FreeNotification方法可以在组件被销毁时通知链表,这样链表就可以将对象引用从链表中删除的。
TClassList 类Contnrs单元中还定义了TClassList类,类定义如下:TClassList = class(TList)protectedfunction GetItems(Index: Integer): TClass;procedure SetItems(Index: Integer; AClass: TClass);publicfunction Add(aClass: TClass): Integer;function Remove(aClass: TClass): Integer;function IndexOf(aClass: TClass): Integer;procedure Insert(Index: Integer; aClass: TClass);property Items[Index: Integer]: TClassread GetItems write SetItems; default;end;不同于前面两个类,这个类继承于TList的类只是将Add, Remove, IndexOf, Insert和Items 调用的参数从指针换成了TClass元类类型。
TOrderedList, TStack和TQueue 类Contnrs单元还定义了其它三个类:TOrderedList, TStack和TQueue,类型定义如下:TOrderedList = class(TObject)privateFList: TList;protectedprocedure PushItem(AItem: Pointer); virtual; abstract;...publicfunction Count: Integer;function AtLeast(ACount: Integer): Boolean;procedure Push(AItem: Pointer);function Pop: Pointer;function Peek: Pointer;end;TStack = class(TOrderedList)protectedprocedure PushItem(AItem: Pointer); override;end;TQueue = class(TOrderedList)protectedprocedure PushItem(AItem: Pointer); override;end;要注意虽然TOrderedList 并不是从TList继承的,但是它在内部的实现时,使用了TList来储存指针。
另外注意TOrderedList类的PushItem 过程是一个抽象过程,所以我们无法实例化TOrderedList 类,而应该从TOrderedList继承新的类,并实现抽象的PushItem方法。
TStack 和TQueue 正是实现了PushItem抽象方法的类,我们可以实例化TStack 和TQueue类作为后进先出的堆栈(LIFO)和先进先出的队列(FIFO)。
下面是这两个的的方法使用说明:·Count 返回列表中的项目数。
·AtLeast 可以用来检查链表的大小,判断当前列表中的指针数目是否大于传递的参数值,如果为True表示列表中的项目数大于传来的参数。
·对于TStack类Push 方法将指针添加到链表的最后,对于TQueue类Push 方法则将指针插入到链表的开始。