Delphi中的关键字与保留字
分类整理 Delphi 中的“关键字”和“保留字”,方便查询
感谢原作者的收集整理!
关键字和保留字的区别在于,关键字不推荐作标示符(编译器已经内置相关函数或者留给保留实现),二保留字是根本不可能作标示符(编译时有警示!)
【系统保留字】
and array as asm
begin case class const
constructor destructor dispinterface div
do downto else end
except exports file finalization
finally for function goto
if implementation in inherited
initialization inline interface is
label library mod nil
not object of or
out packed procedure program
property raise record repeat
resourcestring set shl shr
string then threadvar to
try type unit until
uses var while with
xor
【系统关键字】
absolute abstract assembler automated
cdecl contains default dispid
dynamic export external far
forward implements index message
name near nodefault on
overload override package pascal
private protected public published
read readonly register reintroduce
requires resident safecall stdcall
stored virtual write writeonly
{-------------------------------------------------------------------------------
名称:【program】、【library】、【package】、【unit】
功能:用于标识程序文件、动态链接库文件、包文件、单元文件的文件头。
program :编译后生成 exe 文件,可以直接执行。
library :编译后生成 dll 文件,可被其他程序调用。
package :编译后生成 bpl 文件,可被安装到
delphi 的控件库中,从而在以后
的开发中使用控件。
unit :编译后生成 dcu 文件,将被编译到 exe 和 dll 文件中。
-------------------------------------------------------------------------------}
{ 空程序文件 Test.dpr }
program Project1;
begin
end.
----------
{ 空动态链接库文件
Test.dpr }
library Project1;
begin
end.
----------
{ 空包文件 Test.dpk }
package Package1;
end.
----------
{ 空单元文件 Test.pas }
unit Unit1;
interface
implementation
end.
{-------------------------------------------------------------------------------
名称:【contains】、【requires】
功能:与包文件相关的关键字。
contains :用于指出某个包(package)是否包含某个文件,用
contains 引入
的文件必须被添加到包文件中,它可以避免关键文件的引用丢失。
requires :指出编译 package 时的必备条件。若
requires 的条件未满足,则
不允许编译包。
-------------------------------------------------------------------------------}
package MyPackage;
requires
{ 包需要运行在下面的环境中 }
rtl, clx;
contains
{ 包需要用到下面的文件 }
DB, DBMyControl;
end.
{-------------------------------------------------------------------------------
名称:【interface】、【implementation】、【initialization】、【finalization】
功能:与单元文件相关的关键字。
interface :单元文件的接口部分,也用于定义接口类型。
implementation :单元文件的实现部分。
initialization :单元文件的初始化部分。
finalization :单元文件的反初始化部分。
-------------------------------------------------------------------------------}
{ 单元文件结构 }
unit Unit1;
interface
{ 引用其他单元、定义数据类型、定义过程函数、定义变量常量等 }
{ 此处定义的类型或数据对其他单元是可见的(可访问的) }
implementation
{ 引用其他单元、实现接口部分定义的类型、过程、函数的具体代码 }
{ 此处定义的类型或变量只对本单元可见 }
initialization
{ 这里编写单元被载入时所要调用的方法 }
{ 通常是初始化一些不能自动初始化的对象,也可以不用 }
{ initialization 最常用的情况是对 OLE 对象做初始化 }
finalization
{ 这里编写单元被释放时所要调用的方法 }
{ 通常是释放掉单元中不能自动释放的对象,也可以不用 }
{ finalization 最常用的情况是对 OLE 对象做反初始化 }
end.
----------
{ 定义接口类型 }
IEnumerator = interface(IInterface)
function GetCurrent: TObject;
function MoveNext: Boolean;
procedure Reset;
property Current: TObject read GetCurrent;
end;
{-------------------------------------------------------------------------------
名称:【uses】
功能:用于引用一个外部的单元。
uses 语句通常放在一个单元的接口部分或实现部分。
-------------------------------------------------------------------------------}
{ 程序文件 }
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
begin
end.
----------
{ 单元文件 }
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants,
Classes;
implementation
uses
StrUtrls;
end.
{-------------------------------------------------------------------------------
名称:【type】
功能:用于声明各种类型。
-------------------------------------------------------------------------------}
type
{ 声明接口 }
IMyInterface = interface
end;
{ 声明类指针 }
PMyObject = ^TMyObject;
{ 声明类 }
TMyObject = class(TObject)
end;
{ 声明结构 }
TMyRecord = record
end;
{ 声明函数 }
TMyFunc = function(I:
Integer): string;
{ 声明自定义类型 }
TCol = (cItemA, cItemB, cItemC);
TColSet = set of TCol;
TLatter = 'A' .. 'Z';
TInt = Integer;
{-------------------------------------------------------------------------------
名称:【var】、【const】、【resourcestring】、【threadvar】、【absolute】
功能:用于声明变量和常量
var :声明变量,或者声明函数的参数为传址参数。
const :声明常量,或者声明函数的参数为常量参数。
resourcestring :声明资源字符串。
threadvar :声明一个线程内变量,此变量仅供各个线程内部使用。如果在线程外
初始化该变量,则初始化的内容不会被传入线程内,当线程创建时,该变量为空,
且被认为是线程内的私有变量,与线程外的该变量互不干扰,与其它线程内的该变
量也互不干扰。threadvar 必须声明为全局变量,然后在各个线程内使用。
Delphi 说在线程内使用的 threadvar 必须在线程结束前手动释放其占用的空间。
比如 S :=
''; 即将字符串资源释放。关于资源释放,Delphi 没有更多解释。
absolute :定义一个变量与另一个变量地址相同
-------------------------------------------------------------------------------}
{ 关于变量和常量的声明 }
procedure TForm1.Button1Click(Sender: TObject);
resourcestring
{ 声明资源字符串 }
rsButtonCaption = '测试(&T)';
const
{ 声明常量 }
conMax = 50;
var
{ 声明变量 }
iNum: Integer;
bFlag: Boolean;
begin
Button1.Caption := rsButtonCaption;
iNum := Random(100);
bFlag := iNum >= conMax;
Caption := IntToStr(iNum) + ' - ' + BoolToStr(bFlag, True);
end;
----------
{ 关于 threadvar }
unit Form1Unit;
interface
uses
Windows, Messages, SysUtils, Variants,
Classes, Graphics, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
{ NOTE: 将
GlobalStr 的定义由 var 改为
threadvar 来观察不同 }
var { 线程内外共用此变量 }
// threadvar { 线程内将创建此变量的一个副本,线程内外此变量互不干扰 }
GlobalStr: string;
type
TTLSThread = class(TThread)
private
FNewStr: String;
protected
procedure Execute; override;
public
constructor Create; overload;
constructor Create(const ANewStr: String); overload;
end;
procedure SetShowStr(const S: String; const sTitle: string = '');
begin
if S = '' then
MessageBox(0,
PChar(GlobalStr), PChar(sTitle), MB_OK)
else
GlobalStr := S;
end;
constructor TTLSThread.Create;
begin
inherited Create(False);
end;
constructor TTLSThread.Create(const ANewStr: String);
begin
FNewStr := ANewStr;
inherited Create(False);
end;
procedure TTLSThread.Execute;
begin
FreeOnTerminate := True;
SetShowStr(FNewStr);
SetShowStr('', '线程内 - 线程执行时');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SetShowStr('线程外的 GlobalStr 变量');
SetShowStr('', '线程外 - 线程创建前');
TTLSThread.Create('线程内的 GlobalStr 若为 threadvar 类型,则与线程外的
GlobalStr 无关');
Sleep(100);
SetShowStr('', '线程外 - 线程创建后,观察
GlobalStr 在线程内外是否不同');
end;
end.
----------
{ 同地址变量 }
{ 下面的代码声明了变量
ucLen 的起始地址与 ShortStrig 型变量 sStr
相同,由
于 ShortString 的第 0 个位置保存了字符串的长度,所以 ucLen 的值即为字符
串的长度。 }
procedure TForm1.Button1Click(Sender: TObject);
var
sStr: ShortString;
ucLen: Byte absolute sStr;
begin
sStr := '1234567890';
Caption := IntToStr(ucLen);
end;
{-------------------------------------------------------------------------------
名称:【begin】、【end】
功能:begin end :组合使用,可以表示一段代码或一个程序的开始和结束。
end 还可以与 case, class, interface, asm, unit, package 等相匹配。
对于语句块,end 后必须添加分号。而对于单元或包,end 后必须添加句点。
在 If 语句中 else
关键字前的 end 后不允许添加分号。
-------------------------------------------------------------------------------}
{ 一段代码的开始和结束 }
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
I := Random(100);
if I < 50 then
begin
Caption := IntToStr(I);
end
else
begin
Caption := IntToStr(I - 50);
end;
end;
----------
{ 程序文件的开始和结束 }
program Project1;
begin
end.
----------
{ 包文件的开始和结束,不需要
begin }
package Package1;
end.
----------
{ 类的开始和结束,不需要
begin }
TMyObject = class(TObject)
end;
{-------------------------------------------------------------------------------
名称:【if】、【then】、【else】、【case】
功能:if then else 组合使用,构成条件判断语句,当不需要 else 时,可以省略 else
,当 else
与 if 配合使用时,else 前面的一条语句不能以分号结束。
case else 组合使用,构成条件选择语句。
else 还可以与 try
except on 语句组合,构成异常处理语句,详见 except。
-------------------------------------------------------------------------------}
{ if then else(条件判断) }
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
I := Random(100);
if I < 50 then
Caption := IntToStr(I)
else
Caption := IntToStr(I - 50);
end;
end;
{ if then(条件判断,无 else) }
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
I := Random(100);
if I < 50 then
Caption := IntToStr(I);
end;
----------
{ case else(条件选择) }
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
I := Random(100);
case I of
1 .. 33:
Caption := '小';
34 .. 66:
Caption := '中';
67 .. 99:
Caption := '大';
else
Caption := '0';
end;
end;
{-------------------------------------------------------------------------------
名称:【for】、【to】、【downto】、【do】、【while】、【repeat】、【until】
功能:for to(或downto) do 组合使用,构成 for 循环语句。
while do 组合,构成 while 循环语句。
repeat until 组合,构成 repeat 循环语句。
for 还可以与 in 组合,构成 for 循环语句,详见 in
do 还可以与 with
组合构成默认对象语句,详见 with
do 还可以与 try
except on 组合使用,构成异常处理语句,详见 except。
-------------------------------------------------------------------------------}
{ for 循环语句,循环变量递增 }
procedure TForm1.Button1Click(Sender: TObject);
var
I, iSum: Integer;
begin
iSum := 0;
for I := 1 to 100 do
iSum := iSum + I;
Caption := IntToStr(iSum); { 结果 5050 }
end;
{ for 循环语句,循环变量递减 }
procedure TForm1.Button1Click(Sender: TObject);
var
I, iSum: Integer;
begin
iSum := 0;
for I := 100 downto 1 do
iSum := iSum + I;
Caption := IntToStr(iSum); { 结果 5050 }
end;
----------
{ while 语句 }
procedure TForm1.Button1Click(Sender: TObject);
var
I, iSum: Integer;
begin
iSum := 0;
I := 0;
while I <= 100 do begin
iSum := iSum + I;
Inc(I);
end;
Caption := IntToStr(iSum); { 结果 5050 }
end;
----------
{ repeat 语句 }
procedure TForm1.Button1Click(Sender: TObject);
var
I, iSum: Integer;
begin
iSum := 0;
I := 0;
repeat
iSum := iSum + I;
Inc(I);
until I > 100;
Caption := IntToStr(iSum); { 结果 5050 }
end;
{-------------------------------------------------------------------------------
名称:【with】
功能:用于设置默认对象,简化代码。
-------------------------------------------------------------------------------}
{ with 语句 }
procedure TForm1.Button1Click(Sender: TObject);
begin
// 这里的 4 行代码可以用 with 语句简化输入:
// (Sender as TButton).Left := 0;
// (Sender as TButton).Top := 0;
// (Sender as TButton).Width := 120;
// (Sender as TButton).Height := 60;
with (Sender as TButton) do
begin
Left := 0;
Top := 0;
Width := 120;
Height := 60;
end;
Caption := '测试 with 语句';
Width := Width div 2;
Height := Height div 2;
end;
{-------------------------------------------------------------------------------
名称:【label】、【goto】
功能:goto :无条件跳转
label :定义跳转标签,goto 语句只能跳转到已定义的标签位置。
-------------------------------------------------------------------------------}
procedure TForm1.Button1Click(Sender: TObject);
label
AA;
var
I, iNum: Integer;
begin
I := 0;
iNum := 0;
AA:
inc(I);
iNum := iNum + I;
if I < 10 then
goto AA;
Caption := IntToStr(iNum); { 结果 55 }
end;
{-------------------------------------------------------------------------------
名称:【asm】、【assembler】
功能:asm 用于在程序中插入汇编代码。
使用汇编代码时, 必须使用 asm ...end; 的结构,而非
begin ... end;
assembler 用于支持早期的汇编, 如80386等。它和 asm 的区别是 asm 允许使用
Win32 汇编, 而 assembler 只允许 80x86 汇编, 它不允许 Invoke 语句的出现。
-------------------------------------------------------------------------------}
function IntToHex(Value: Integer; Digits: Integer): string;
asm
CMP EDX, 32
JBE @A1
xor
EDX, EDX
@A1: PUSH ESI
MOV ESI, ESP
SUB ESP, 32
PUSH ECX
MOV ECX, 16
CALL CvtInt
MOV EDX, ESI
POP EAX
CALL System.@LStrFromPCharLen
ADD ESP, 32
POP ESI
end;
{-------------------------------------------------------------------------------
名称:【and】、【or】、【not】、【xor】、【shl】、【shr】、【div】、【mod】
功能:Delphi 运算符。
and(逻辑与 或 按位与) or(逻辑或 或 按位或) not(逻辑非 或 按位否)
xor(逻辑异或 或 按位异或) shl(位左移) shr(位右移)
div(整除) mod(求余数)
xor(逻辑异或 或 按位异或)我喜欢把它叫做“逻辑异”,只要 xor 两边的布尔
值不相同(相异),结果就为 True,否则就为 False。只要 xor 两边的位状态不
同(0 和 1 不同),结果就为 1,否则就为 0。
-------------------------------------------------------------------------------}
{ 逻辑与 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, B: Integer;
begin
A := 1;
B := -1;
if (A > 0) and (B > 0) then
Caption := 'True'
else
Caption := 'False'; { 结果 False }
end;
{ 逻辑或 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, B: Integer;
begin
A := 1;
B := -1;
if (A > 0) or (B > 0) then
Caption := 'True' { 结果 True }
else
Caption := 'False';
end;
{ 逻辑非 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, B: Integer;
begin
A := 1;
B := -1;
if not A >
B then
Caption := 'True'
else
Caption := 'False'; { 结果 False }
end;
{ 逻辑异或 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, B: Integer;
begin
A := 1;
B := -1;
if (A > 0) xor (B > 0) then
Caption := 'True' { xor 两边的布尔值不同,结果 True
}
else
Caption := 'False';
end;
----------
{ 按位与 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, B, C: Integer;
begin
A := 360;
B := 120;
C := A and B;
Caption := IntToStr(C); { 结果:104 }
end;
{ 按位或 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, B, C: Integer;
begin
A := 360;
B := 120;
C := A or B;
Caption := IntToStr(C); { 结果:376 }
end;
{ 按位否 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, C: Integer;
begin
A := 360;
C := not A;
Caption := IntToStr(C); { 结果:-361 }
end;
{ 按位异或 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, B, C: Integer;
begin
A := 360;
B := 120;
C := A xor B;
Caption := IntToStr(C); { 结果:272 }
end;
{ 位左移 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, C: Integer;
begin
A := 360;
C := A shl 1; { 相当于 A 乘以 2 的 1 次方 }
Caption := IntToStr(C); { 结果:720 }
end;
{ 位右移 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, C: Integer;
begin
A := 360;
C := A shr 1; { 相当于 A 除以 2 的 1 次方 }
Caption := IntToStr(C); { 结果:180 }
end;
----------
{ 整除 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, B, C: Integer;
begin
A := 36;
B := 5;
C := A div B;
Caption := IntToStr(C); { 结果:7 }
end;
{ 求余数 }
procedure TForm1.Button1Click(Sender: TObject);
var
A, B, C: Integer;
begin
A := 36;
B := 5;
C := A mod B;
Caption := IntToStr(C); { 结果:1 }
end;
{-------------------------------------------------------------------------------
名称:【try】、【finally】、【except】、【on】、【raise】
功能:这些都是异常处理语句。
try finally 组合使用,构成异常处理语句。先执行 try 部分的语句,无论 try
部分是否执行成功,finally 部分都会被执行。
try except on 组合使用,构成异常处理语句。正常情况下执行 try 部分的语句。
如果发生异常,则执行 except 后的语句。
raise 用于抛出异常。如果希望通过外部程序处理异常,或是在异常发生时重新将
异常抛出,可以使用 raise 语句。异常被抛出后,raise
后面的代码将不被执行。
-------------------------------------------------------------------------------}
{ try finally(异常处理) }
procedure TForm1.Button1Click(Sender: TObject);
var
Strs: TStringList;
begin
Strs := TStringList.Create;
try
Strs.Add('finally Test');
Caption := Strs[0];
finally
Strs.Free;
end;
end;
----------
{ try except on else(异常处理) }
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
S: String;
begin
S := '123A';
try
I := StrToInt(S);
except
on EZeroDivide do
Caption := 'EZeroDivide';
on EOverflow do
Caption := 'EOverflow';
else
Caption := 'Unknow Error';
end;
end;
----------
{ raise 抛出异常 }
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
{ 普通代码中抛出异常 }
I := -1;
if I < 0 then
raise exception.Create('整数不能小于 0');
ShowMessage('异常被抛出后...');
end;
{ raise 抛出异常 }
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
S: string;
begin
{ try except 中抛出异常 }
try
S := '123A';
I := StrToInt(S);
except
on E:
exception do
raise exception.Create(E.Message);
end;
ShowMessage('异常被抛出后...');
end;
{-------------------------------------------------------------------------------
名称:【procedure】、【function】、【forward】、【out】
功能:Delphi 函数、过程相关关键字。
procedure :定义过程,过程无返回值。主要用来执行一系列动作。还可以用来声
明自定义函数类型。
function :定义函数,函数有返回值。主要用来计算某一结果。还可以用来声明
自定义函数类型。
forward :用于函数(或过程)的前置声明,这样可以使代码中“较先实现的函数
”可 以调用“较后实现的函数”,如果“较后实现的函数”不做前置声明,则它不
能被前面的函数调用。
out :定义函数(或过程)的参数为传出类型,out 类型的参数用来将函数的执行
结果通过此参数返回给调用者(传地参数)。调用者在调用函数时,不需要给 out
类型的参数赋值,赋了也没用。
还有之前提到的一个关键字 var :定义函数(或过程)的参数为传址类型,var
类型的参数在函数内的一切改变都会返回给调用者,调用者也可以在调用函数前,
给 var 参数赋值,然后传递到函数里面使用。
-------------------------------------------------------------------------------}
{ 函数前置声明 }
function CalcPerimeter(R: Double): Double; forward;
function CalcArea(R: Double): Double; forward;
{ 过程:执行一系列动作,显示圆的半径、周长、面积信息 }
procedure ShowInfo(Radius: Double);
var
sRadius: string;
sPerimeter: string;
sArea: string;
begin
sRadius := FloatToStr(Radius);
{ 如果不做前置声明,则这里无法调用
CalcPerimeter }
sPerimeter :=
FloatToStr(CalcPerimeter(Radius));
{ 如果不做前置声明,则这里无法调用
CalcArea }
sArea := FloatToStr(CalcArea(Radius));
ShowMessage('半径:' + sRadius + #13#10 +
'周长:' + sPerimeter + #13#10 +
'面积:' + sArea);
end;
{ 函数:计算圆的周长 }
function CalcPerimeter(R: Double): Double;
begin
{ 2 乘以 派 乘以 半径,Pi 是系统函数,计算圆周率 }
Result := 2 * Pi *
R;
end;
{ 函数:计算圆的面积 }
function CalcArea(R: Double): Double;
begin
{ 派 乘以 半径的平方,Pi 是系统函数,计算圆周率 }
Result := Pi * R * R;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowInfo(10.5);
ShowInfo(30.25);
end;
----------
{ 声明自定义函数类型
TMyFunc }
type
TMyFunc = function(I:
Integer): Integer;
{ 某个函数 }
function GetCountNum(Num: Integer): Integer;
var
I: Integer;
begin
Result := 0;
for I := 0 to Num do
begin
Result := Result + I;
end;
end;
{ 这里只是简单测试,自定义函数类型一般用作函数或过程的参数 }
procedure TForm1.Button1Click(Sender: TObject);
var
MyFunc: TMyFunc;
iCountNum: Integer;
begin
{ 将某个同类型的函数赋值给
MyFunc }
MyFunc := GetCountNum;
{ 然后 MyFunc 就可以像普通函数一样使用了 }
iCountNum := MyFunc(100);
Caption := IntToStr(iCountNum); { 结果 5050 }
end;
----------
{ var 和 out 测试 }
{ 过程是没有返回值的,但是我们可以通过 var 或 out 参数来返回数据 }
procedure Test(var I: Integer; out S: String);
begin
{ 先看看传进来的是什么 }
ShowMessage('参数I:' +
IntToStr(I) + #13#10 + '参数S:' +
S); { S 将为空 }
{ 修改参数的值,看能否传递到过程外面去 }
I := I + 100;
S := S + 'AfterStr'; { 如果我们将这一行代码注释掉,则 S 将返回空字符串 }
end;
procedure TForm1.Button1Click(Sender: TObject);
var
A: Integer;
B: String;
begin
A := 1;
B := 'ABC';
Test(A, B); { 'ABC' 无法传入到函数中 }
Caption := IntToStr(A ) + ' ' +
B; { 结果 101
AfterStr }
end;
{-------------------------------------------------------------------------------
名称:【cdecl】、【pascal】、【stdcall】、【safecall】、【register】
【varargs】
功能:函数(或过程)的调用协定,各个调用协定的要求内容太多,这里只是简单说明,
具体可以翻查相关资料。
cdecl :规定了从 C 或 C++ 编写的 DLL 中调用函数所必须遵守的规则。它可以
将 C 或 C++ 中的数据类型转换为
Delphi 的类型。
pascal :规定参数从左向右传递。函数调用时要对所有的变量进行初始化,避免
因异步线程调用而产生的错误,保留它是为了向下兼容。
stdcall :规定参数从右向左传递。同时 stdcall 规定, 被调函数是大小写敏感
的。在调用函数时,如果函数名中有一个字符的大小写出错,则该函数将调用失败。
safecall :规定被 COM 调用的函数所必须遵守的规则。在编译时,safecall
声
明的函数被编译成与 COM 接口兼容的。
register :Delphi 专用的函数调用协定,直接通过寄存器传递参数,因此传递速
度非常块。
register 关键字也被用来注册控件。
varargs :标示了引用参数,它必须和 cdecl 关键字联用,表明允许调用的函数
使用引用传递。
-------------------------------------------------------------------------------}
{ cdecl }
// { 例如 C++ 中的代码 }
// int CFun(int i)
// {
// return i*2;
// }
{ 如果这个函数被编译在
Test.dll 中, 则用 Delphi 调用时必须使用如下方式 }
function CFun(i: Integer): Integer; Cdecl; external 'Test.dll';
----------
{ pascal }
function Test(I, J, K, L: Integer): Integer; pascal;
begin
Result := I * J * K * L;
end;
----------
{ stdcall }
Library Test;
function Func1(I, J, K, L: Integer): Integer; stdcall;
begin
Result := I * J * K * L;
end;
exports
Func1;
begin
end.
{ 主调方函数声明 }
function Func1(I, J, K, L: Integer): Integer; stdcall; external 'Test.dll';
----------
{ safecall }
{ 编译时,声明函数的调用协定为
safecall 类型 }
procedure MyFunc(S: WideString); safecall;
{ 编译后函数成为与 COM 接口兼容的类型 }
procedure MyFunc(S: PAnsiString);
----------
{ register }
function Func1(I, J, K, L: Integer): Integer; register;
begin
Result := I * J * K * L;
end;
----------
{ 注册控件 }
procedure Register;
begin
RegisterComponents('Sample', [TTest]);
end;
---------
{ varargs }
{ 这段代码从 C++ 的类库中引用了 Printf 函数,并允许按引用的方式传入参数 }
function printf(Format: PChar): Integer; cdecl; varargs;
{-------------------------------------------------------------------------------
名称:【class】
功能:定义类类型,或声明一个类方法。
具体参见
Delphi 相关资料。
-------------------------------------------------------------------------------}
{ 定义空类,默认继承自
TObject }
type
TMyObject = class
end;
----------
{ 定义 TMyObject 类并测试类方法 }
type
TMyObject = class(TObject)
private
FName: string;
protected
public
{ 定义类方法,类方法可以直接通过类调用 }
class procedure ShowResult;
published
property Name: string read FName write FName;
end;
{ 实现类方法 }
class procedure TMyObject.ShowResult;
begin
ShowMessage('调用成功!');
end;
{ 调用类方法 }
procedure TForm1.Button1Click(Sender: TObject);
begin
TMyObject.ShowResult; { 直接通过 TMyClass 调用,不用创建实例 }
end;
{-------------------------------------------------------------------------------
名称:【record】、【packed】
功能:record :定义结构类型。
一个结构体可以视为一个不需要实例化的类(某些地方和对象用法不同)。
具体参见
Delphi 相关资料。
packed :用于对结构类型对象或数组类型对象进行打包,打包后的对象体积能显著
减小。打包后元素对齐位置也会发生变化,不再对齐到与 CPU 处理能力相匹配的位
置,因此打包后的对象,处理速度会降低。详细信息请查阅相关资料。
-------------------------------------------------------------------------------}
{ 定义 record 类型 }
type
TMyRec = record
Name: string;
Age: Cardinal;
Sex: Boolean;
end;
----------
{ 定义 record 类型,用法类似于 class }
type
TMyRec = record
private
FName: string;
public
procedure ShowResult;
property Name: string read FName write FName;
end;
{ 实现 record 方法 }
procedure TMyRec.ShowResult;
begin
ShowMessage('调用成功!');
end;
{ 调用 record 方法 }
procedure TForm1.Button1Click(Sender: TObject);
var
MyRec: TMyRec;
begin
MyRec.Name := 'Record 测试';
ShowMessage(MyRec.Name);
MyRec.ShowResult;
end;
----------
{ 打包 }
type
{ 未打包 }
TMyRecA = record
Name: string;
Age: Byte;
Sex: Boolean;
end;
{ 打包 }
TMyRecB = packed record
Name: string;
Age: Byte;
Sex: Boolean;
end;
{ 未打包 }
TMyArrayA = array [0 .. 32] of Byte;
{ 打包 }
TMyArrayB = packed array [0 .. 32] of Byte;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(IntToStr(SizeOf(TMyRecA)));
ShowMessage(IntToStr(SizeOf(TMyRecB)));
ShowMessage(IntToStr(SizeOf(TMyArrayA)));
ShowMessage(IntToStr(SizeOf(TMyArrayB)));
end;
{-------------------------------------------------------------------------------
名称:【object】
功能:定义对象类型,或声明“对象函数”或“对象过程”。
定义对象类型是 Object Pascal 中的一个古老的功能,这个功能现在已经被
class 取代。具体参见 Delphi 相关资料。
-------------------------------------------------------------------------------}
{ 定义对象 }
type
MyObject = object
private
FName: string;
protected
public
procedure ShowResult;
property Name: string read FName write FName;
end;
{ 实现对象方法 }
procedure MyObject.ShowResult;
begin
ShowMessage('调用成功!');
end;
{ 调用对象方法 }
procedure TForm1.Button1Click(Sender: TObject);
var
MyObj :MyObject;
begin
MyObj.Name := 'Object 测试';
ShowMessage(MyObj.Name);
MyObj.ShowResult;
end;
----------
type
{ 该函数不能是独立的函数,必须是某个对象的成员 of Object }
TMyFun = function(I:
Integer): Integer of object;
{ 该过程不能是独立的过程,必须是某个对象的成员 of Object }
TMyProc = procedure(S: string) of object;
{-------------------------------------------------------------------------------
名称:【automated】、【private】、【protected】、【public】、【published】
功能:定义类(或结构、对象)成员的可访问类型。
automated :自动成员,它能够使程序的版本向下兼容。
ComObj 单元内的成员及其实例不能使用 automated 访问区分符。
不能用于结构类型和对象类型。
private :私有成员,只有类所在单元可以访问。
protected :保护成员,只有子类可以访问,不能用于结构类型。
public :公开成员,可以在任何地方被访问。
published :发布成员,可以在运行时被访问,不能用于结构类型和对象类型。
-------------------------------------------------------------------------------}
type
TMyObject = class
automated
{ 这里放置自动类型的成员 }
private
{ 这里放置私有类型的成员 }
protected
{ 这里放置保护类型的成员 }
public
{ 这里放置公开类型的成员 }
published
{ 这里放置发布类型的成员 }
end;
----------
{ 关于 automated }
type
TMyObject = class
automated
Str:WideString;
end;
{ 如果在程序的下一个版本中, 将 Str 修改成 }
type
TMyObject = class
automated
Str: AnsiString;
end;
{ 则新版本的 Str 变量能够接受旧版本的 WideString 型数据,并自动转换成
AnsiString。
在实际开发中,如果没有特殊的需要,一般不用 automated 访问区分符。}
{-------------------------------------------------------------------------------
名称:【constructor】、【destructor】、【property】
功能:定义类类型或对象类型的构造函数,析构函数和属性。
constructor :声明或定义一个构造函数,可以用于类类型、对象类型、结构类型。
结构类型不允许定义无参数的构造函数。
destructor :声明或定义一个析构函数,可以用于类类型、对象类型。
析构函数主要用来释放对象资源。析构函数只允许覆盖,不允许重载。
property :声明或定义一个属性,可以用于类类型、对象类型、结构类型。
属性分为显式属性和隐式属性两种,只有声明为 published 访问类型的属性才是
显式属性,才可以直接在对象查看器中查看。
事件也是属性的一种,可以在 published 下用 property 进行声明。
-------------------------------------------------------------------------------}
{ 定义类类型 }
type
TMyObj = class(TObject)
private
FName: string;
FAge: Cardinal;
FOnTexChange: TEvent; { 事件 }
protected
public
{ 构造函数 }
constructor Create;
{ 析构函数 }
destructor Destroy; override;
published
{ 发布属性 }
property Name: string read FName write FName;
property Age: Cardinal read FAge write FAge;
{ 发布事件 }
property OnTextChange: TEvent read FOnTexChange write FOnTexChange;
end;
----------
{ 定义结构类型 }
type
MyRec = record
private
FName: string;
FAge: Cardinal;
public
{ 构造函数 }
constructor Create(Name: string);
{ 不能有析构函数 }
{ 公开属性 }
property Age: Cardinal read FAge write FAge;
end;
----------
{ 定义对象类型 }
type
MyObj = object
private
FName: string;
FAge: Cardinal;
protected
public
{ 构造函数 }
constructor Create;
{ 析构函数 }
destructor Destroy; override;
{ 公开属性 }
property Name: string read FName write FName;
property Age: Cardinal read FAge write FAge;
end;
{-------------------------------------------------------------------------------
名称:【read】、【write】、【default】、【nodefault】
【readonly】、【writeonly】、【stored】、【message】
功能:定义属性的各种参数
read :用于标识属性读取时所使用的成员或方法。
write :用于标识属性写入时所使用的成员或方法。
default :指示属性的默认值,或指示一个属性为类的默认属性。
只有有序类型的属性才允许默认值的存在, 否则必须在构造函数中初始化属性值。
nodefault :指示一个属性不允许有默认值,这通常用在继承中。
readonly :指示一个属性为只读。
当
readonly 设为 True 时, 不允许用户修改属性, 只能通过其他对象来操作
writeonly :指示一个属性为只写。
当
writeonly 设为 true 时,不允许用户读取属性,只能通过其他对象来操作
stored :指示一个属性的值是否能被保留,若指定了True,则允许对属性值进行
赋值撤销的操作。
message :用于声明消息方法。
带有 message
的方法必须指出接收的消息类型,并通过引用将消息传入方法中,
以便进行处理。
用户可以自定义消息,自定义消息也能够被 message 接收,并引发事件。
-------------------------------------------------------------------------------}
{ 属性的读取 }
type
TMyObject = class(TObject)
private
FValue: Integer;
published
{ 表明 Value 属性从
FValue 成员上读出值 }
property Value: Integer read FValue;
end;
----------
{ 属性的写入 }
type
TMyObject = class(TObject)
private
FValue: Integer;
published
{ 表明 Value 属性的值写入到 FValue 成员上 }
property Value: Integer write FValue;
end;
----------
{ 默认值和默认属性 }
type
TMyObject = class(TObject)
private
FAuto: Boolean;
FCount: Integer;
FNameList: TStrings;
public
constructor Create;
{ 属性默认值 default True、
default 0 }
property Auto: Boolean read FAuto write FAuto default True;
property Count: Integer read FCount write FCount default 0;
{ 默认属性 default }
property Names[Index: Integer]: TStrings read FNameList
write FNameList default;
end;
constructor TMyObject.Create;
begin
inherited;
{ 分配对象资源 }
FNameList := TStrings.Create;
{ 设置属性默认值 }
FAuto := True;
end;
----------
{ 去掉默认值 }
type
TMyObjA = class
private
FValue: Integer;
published
property Value: Integer read FValue write FValue default 0;
end;
TMyObjB = class(TMyObjA)
published
property Value: Integer read FValue write FValue nodefault;
end;
{ 由上例可知, TMyObjA 中的 Value 有默认值 0,TMyObjB 继承了 TMyObjA,所以也继承
了其默认值, 在此用 NoDefault 去掉默认值。 }
----------
{ 只读属性 }
property ReadOnly;
----------
{ 只写属性 }
property WriteOnly;
----------
{ 保留属性值 }
type
TComponent = class
private
FName: TComponentName;
published
property Name: TComponentName read FName write SetName stored False;
end;
----------
{ 声明消息方法 }
unit Form1Unit;
interface
uses
Windows, Messages, SysUtils, Variants,
Classes, Graphics,
Controls, Forms, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure Refresh(var Msg: TMessage); message WM_SIZE;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ 此方法捕捉窗口尺寸被改变的消息 }
procedure TForm1.Refresh(var Msg:
TMessage);
begin
{ 先将窗口的尺寸显示在标题栏中 }
Caption := IntToStr(Width) + ' - ' + IntToStr(Height);
{ 再调用默认消息处理函数,重绘窗口 }
inherited;
end;
{ 随机调整窗口的大小 }
procedure TForm1.Button1Click(Sender: TObject);
var
Size: Integer;
begin
{ 先将按钮自身移到窗口左上角,以免窗口缩小后被遮挡 }
(Sender as TButton).Left := 0;
(Sender as TButton).Top := 0;
{ 获取一个随机数,可正可负 }
Randomize;
Size := Random(100) - 50;
{ 设置窗口的新大小 }
Width := Width + Size;
Height := Height + Size;
{ 当窗口大小改变后,就会触发
WM_SIZE 消息,从而调用我们定义的 TForm1.Refresh }
end;
end.
{-------------------------------------------------------------------------------
名称:【array】、【file】、【set】、【string】
功能:定义各种数据类型,或声明各种数据类型的变量。
array :声明一个数组。
file :声明一个文件类型。
set :声明一个集合。
string :声明一个字符串。
-------------------------------------------------------------------------------}
{ 定义各种数据类型 }
type
TMyArray = array[0..9] of string; { 声明静态数组 }
TCharArray = array of Char; { 声明动态数组 }
TButtonFile = file of TButton; { 声明 TButton 格式的文件类型 }
TIntFile = file of Integer; { 声明 Integer 格式的文件类型 }
TLatterSet = set of 'A'..'Z'; { 声明大写字母集合 }
TByteSet = set of byte; { 声明字节集合 }
TName = string[32]; { 声明 32 个自己长度的
ShortString 类型 }
procedure TForm1.Button1Click(Sender: TObject);
var
{ 声明各种数据类型的变量 }
MyArray1: TMyArray;
MyArray2: array of Char;
MyFile1: TButtonFile;
MyFile2: file of Integer;
MySet1: TLatterSet;
MySet2: set of 'A'..'Z';
Name1: TName;
Name2: string[255];
Name3: string;
I: Integer;
begin
{ 数组类型测试 }
SetLength(MyArray2, 26);
for I := Low(MyArray2) to High(MyArray2) do
MyArray2[I] := Chr(65 + I);
ShowMessage(string(MyArray2));
{ 集合类型测试 }
MySet1 := ['A'..'Z'];
MySet2 := MySet1;
if 'A' in MySet1 then ShowMessage('Found
A in MySet1');
if CharInSet('A', MySet2) then ShowMessage('Found
A in MySet2');
end;
{-------------------------------------------------------------------------------
名称:【in】
功能:用于判断一个集合中是否包含某个元素。
也可以被用在 for 语句中,用于循环取出一个集合中的元素。
也用于工程文件中,用于标识某个文件是否被工程所引用。
-------------------------------------------------------------------------------}
procedure TForm1.Button1Click(Sender: TObject);
var
Item: Char;
MySet: set of 'A'..'Z';
begin
{ 初始化集合 }
MySet := ['A'..'Z'];
{ in 用于集合 }
if 'A' in MySet then ShowMessage('A is
in MySet');
{ in 用于 for 语句 }
for Item in MySet do
Caption := Caption + Item;
end;
{ in 用于工程文件 }
program Project1;
uses
Forms,
Unit1 in 'Unit1.pas' {Form1};
begin
end.
{-------------------------------------------------------------------------------
名称:【nil】
功能:指示一个指针(某些对象其实也是指针)为空。
-------------------------------------------------------------------------------}
{ 检测控件是否存在 }
procedure TForm1.Button1Click(Sender: TObject);
var
MyEdit: TEdit;
begin
{ 仅仅释放 }
MyEdit := TEdit.Create(Self);
try
MyEdit.Parent := Self;
MyEdit.Show;
Caption :=
BoolToStr(Assigned(MyEdit), True);
finally
MyEdit.Free;
end;
ShowMessage('控件是否存在:' + BoolToStr(Assigned(MyEdit), True));
{ 释放并 nil }
MyEdit := TEdit.Create(Self);
try
MyEdit.Parent := Self;
MyEdit.Show;
Caption :=
BoolToStr(Assigned(MyEdit), True);
finally
MyEdit.Free;
MyEdit := nil; { 这里的两行代码一般合起来写为 FreeAndNil(MyEdit) }
end;
ShowMessage('控件是否存在:' + BoolToStr(Assigned(MyEdit), True));
end;
{-------------------------------------------------------------------------------
名称:【virtual】、【dynamic】、【abstract】、【inline】、【static】
功能:指示一个类方法的类型。
virtual :虚拟方法可以被子类覆写,虚拟方法可以加快调用速度,但浪费内存。
dynamic :动态方法可以被子类覆写,动态方法可以节省内存,但调用速度没有虚
拟方法快。
abstract :抽象方法可以被子类覆写,abstract 关键字必须与 virtual 或
dynamic 关键字同时使用。
包含“抽象方法”的类称为“抽象类”。抽象类可以被实例化,但实例化的对象不
能调用抽象方法,否则会抛出异常。
inline :定义内联函数或内联汇编代码,内联函数类似于宏,编译器在编译程序
时,会将内联函数的代码直接搬到调用者的代码里面去,作为调用者的一部分,也
就不存在调用内联函数的说法了,直接就是一行行代码。内联函数一般是体积较小
且被频繁调用的函数。内联函数可以提高代码的执行效率。如果没有定义内联函数
,则编译器会自己判断将那些函数作为内联函数处理,以便提高程序的执行效率,
所以一般情况下我们不需要手动指定内联函数。内联说明对于编译器来说只是一种
建议,编译器可以忽略这个建议,如果我们指定了内联函数而编译器觉得不合适,
那么编译器可以拒绝将指定的函数内联。
内联函数不是纯粹的函数,因此不能递归调用。
-------------------------------------------------------------------------------}
{ 虚拟方法 }
TObject = class
public
procedure Dispatch(var Message); virtual;
destructor Destroy; virtual;
end;
----------
{ 动态方法 }
TCustomForm = class
protected
procedure DoHide; dynamic;
procedure DoShow; dynamic;
end;
----------
{ TStrings 中的抽象方法 }
TStrings = class
protected
{ 这里只需要定义,具体功能靠子类去实现 }
function Get(Index: Integer): string; virtual; abstract;
{ 这里只需要定义,具体功能靠子类去实现 }
function GetCount: Integer; virtual; abstract;
end;
----------
{ 测试抽象方法 Delphi XE2
}
type
{ 定义一个抽象方法 }
TMyObject = class(TObject)
public
procedure Test1;
procedure Test2; virtual; abstract;
end;
procedure TMyObject.Test1;
begin
ShowMessage('Test1 OK');
end;
procedure TForm1.Button1Click(Sender: TObject);
var
MyObj: TMyObject;
begin
MyObj := TMyObject.Create;
try
MyObj.Test1;
MyObj.Test2;
{ 此处调用了抽象方法 MyObj.Test,运行时将会抛出异常 }
{ 后面的代码将不被执行 }
Caption := '测试抽象方法';
finally
MyObj.Free;
end;
end;
----------
{ 内联函数 }
function Test(S: string): string; inline;
begin
Result := '显示结果:' + S;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Caption := Test(Caption);
{ 此处调用了内联函数,所以,在编译时,此处的代码就被改成了
Caption := '显示结果:' + Caption;
直接将内联函数的代码搬过来进行编译 }
end;
{-------------------------------------------------------------------------------
名称:【override】、【overload】、【reintroduce】、【inherited】
功能:override :指示子类覆写父类的一个 virtual 或 dynamic 方法。覆盖时必须沿
用被覆盖方法的声明,并且不允许修改原方法的参数和返回类型。
overload :指示重载一个同名函数、过程或方法。重载的同名方法时,必须具备
“参数、类型或顺序不同”的条件。调用重载方法时,根据输入的参数不同来调用
不同的重载方法。
reintroduce :指示重新发布父类的方法。如果要覆盖的方法是静态方法,或是需
要修改方法的参数等,必须用 reintroduce 进行重发布。对于
virtual 或
dynamic 方法,可以直接用 override 进行覆盖。
inherited :调用父类的方法。
-------------------------------------------------------------------------------}
{ 覆写父类的方法 }
type
{ 父类定义三个方法,其中两个可以被覆写,一个抽象方法 }
TMyObjectA = class(TObject)
protected
procedure Test1; virtual;
public
function Test2: string; dynamic; abstract;
function Test3: Integer;
end;
{ 子类继承父类的三个,同时将其中两个改写 }
TMyObjectB = class(TMyObjectA)
protected
procedure Test1; override;
public
function Test2: string; override;
end;
{ 父类 - 方法1}
procedure TMyObjectA.Test1;
begin
ShowMessage('A');
end;
{ 父类 - 方法2 }
{ 抽象方法只定义,不实现 }
{ 父类 - 方法3 }
function TMyObjectA.Test3: Integer;
begin
Result := 1;
end;
{ 子类 - 重写方法1 }
procedure TMyObjectB.Test1;
begin
ShowMessage('B');
end;
{ 子类 - 重写方法2 }
function TMyObjectB.Test2: string;
begin
Result := 'B';
end;
{ 调用各个方法 }
procedure TForm1.Button1Click(Sender: TObject);
var
MyObjB: TMyObjectB;
begin
{ 测试子类 }
MyObjB := TMyObjectB.Create;
try
MyObjB.Test1;
Caption := MyObjB.Test2 +
IntToStr(MyObjB.Test3);
finally
MyObjB.Free;
end;
end;
----------
{ 重载函数 }
function ShowInfo(Info: Boolean): string; overload;
begin
ShowMessage(BoolToStr(Info, True));
end;
function ShowInfo(Info: Integer): string; overload;
begin
ShowMessage(IntToStr(Info));
end;
function ShowInfo(Info: string): string; overload;
begin
ShowMessage(Info);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowInfo('你好吗?');
ShowInfo(123);
ShowInfo(True);
end;
----------
{ 重新发布父类的方法 }
type
{ 父类 }
TMyObjectA = class
procedure Test;
end;
{ 子类 }
TMyObjectB = class(TMyObjectA)
procedure Test; reintroduce;
end;
{ 孙类 }
TMyObjectC = class(TMyObjectB)
procedure Test(I: Integer); reintroduce;
end;
----------
{ 调用父类方法 }
type
{ 父类 }
TMyObjectA = class(TObject)
public
procedure Test1; virtual;
procedure Test2; virtual;
end;
{ 子类 }
TMyObjectB = class(TMyObjectA)
public
procedure Test1; override;
end;
{ 父类 - 虚拟方法1 }
procedure TMyObjectA.Test1;
begin
ShowMessage('父类方法 1');
end;
{ 父类 - 虚拟方法2 }
procedure TMyObjectA.Test2;
begin
ShowMessage('父类方法 2');
end;
{ 子类 - 覆写父类方法1 }
procedure TMyObjectB.Test1;
begin
{ 调用父类方法中的同名方法,即
Test1 }
inherited;
{ 调用父类方法中的
Test2 }
inherited Test2;
ShowMessage('子类方法 1');
end;
procedure TForm1.Button1Click(Sender: TObject);
var
MyObjB: TMyObjectB;
begin
MyObjB := TMyObjectB.Create;
try
MyObjB.Test1;
finally
MyObjB.Free;
end;
end;
{-------------------------------------------------------------------------------
名称:【of】、【as】、【is】
功能:of :用于和其他关键字构成指定的结构。
of可以与
case, class, array, file, set, object 连用。
as :用于将一个类对象当作另一种类型使用。
is :用于判断对象是否属于某一类型。
-------------------------------------------------------------------------------}
{ of 关键字 }
type
TMyClass = class of TEdit;
TMyFun = function(I:
Integer): Integer of Object;
procedure TForm1.Button1Click(Sender: TObject);
var
MyArr : array of Integer;
MyFile : file of Byte;
MySet : set of 'A' .. 'Z';
MyClass : TMyClass;
MyFunc : TMyFun;
begin
case Self.Tag of
0:
Caption := 'Tag Zero';
else
Caption := 'Tag No Zero';
end;
end;
----------
{ as 关键字 }
procedure TForm1.Button1Click(Sender: TObject);
begin
{ Sender 本来是
TObject 类型,现在当作 TButton 类型使用 }
(Sender as TButton).Caption := '测试 as'
end;
----------
{ is 关键字 }
procedure TForm1.Button1Click(Sender: TObject);
begin
{ 显然 Sender 与 TForm 无关 }
if Sender is TForm then ShowMessage('Sender
is TForm');
{ Sender 就是
TButton }
if Sender is TButton then ShowMessage('Sender
is TButton');
{ Sender 继承自
TCustomButton }
if Sender is TCustomButton then ShowMessage('Sender
is TCustomButton');
{ Sender 继承自
TObject }
if Sender is TObject then ShowMessage('Sender
is TObject');
end;
{-------------------------------------------------------------------------------
名称:【implements】
功能:implements :指出了一个属性从接口继承,此时属性被转换成接口对象。通过接口
动态绑定属性,并动态的设定属性值。
还有之前提到的一个关键字 Interface:用于声明一个接口类型。
-------------------------------------------------------------------------------}
{ implements }
type
IMyInterface = interface
procedure P1;
procedure P2;
end;
TMyImplclass = class
procedure P1;
procedure P2;
end;
TMyclass = class(TInterf |
请发表评论