zoukankan      html  css  js  c++  java
  • Delphi中的关键字与保留字

    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(TInterfacedObject, IMyInterface)
        FMyImplClass: TMyImplclass;
        property MyImplClass: TMyImplclass read FMyImplClass
          implements IMyInterface;
        procedure IMyInterface.P1 = MyP1;
        procedure MyP1;
      end;

      // 通过implements声明后, 可以在类声明时指出接口中方法的实体, 如上例中的:
      // procedure IMyInterface.P1 = MyP1;

    ----------

    { Interface 接口类型声明 }

    type
      IMalloc = interface(IInterface)
      ['{00000002-0000-0000-C000-000000000046}']
        function Alloc(Size: Integer): Pointer; stdcall;
        function Realloc(P: Pointer; Size: Integer): Pointer; stdcall;
        procedure Free(P: Pointer); stdcall;
        function GetSize(P: Pointer): Integer; stdcall;
        function DidAlloc(P: Pointer): Integer; stdcall;
        procedure HeapMinimize; stdcall;
      end;



    {-------------------------------------------------------------------------------
      名称:【index】、【near】、【far】、【export】、【exports】
            【external】、【name】、【resident】

      功能:index :用于在属性中标识序号,以便用相同的属性方法(Get,Set)对不同的属
            性进行操作。index 关键字也用于在属性中指出多个元素。

    near :标明函数的调用协定,指出函数可以被本地调用。其他程序可以用 dll 的
            形式调用程序内的函数,保留它是为了向下兼容。

            far :标明了函数调用协定,指出函数可以被远程调用。其他程序可以用 dll 的
            形式调用程序内的函数,保留它是为了向下兼容。

    export :明函数的调用协定,指出函数可以被输出,输出的函数能被本地或远程
            调用。其他程序可以用 dll 的形式调用程序内的函数,保留它是为了向下兼容。

            exports :用于输出对象,它必须被用在接口和实现之间,可以同时输出多个项,
            项与项之间用逗号分开。

            external :用于引用一个外部的或是 OBJ 内的方法。使用 external 关键字时,
            代码必须注意大小写,否则将出现错误。

    name :用于指出方法的别名,对于一个要被外部引用的方法,建议用 name 申请
            方法别名,以避免外部程序改动方法的实体内容。从外部引用一个方法时,如果该
            方法有别名,则必须用 name 进行标识。

            resident :使用 resident,则当 DLLs 装入时,特定的输出信息始终保持在内
            存中。这样当其它应用程序调用该过程时,可以比利用名字扫描 DLL 入口降低时
            间开销。对于那些其它应用程序常常要调用的过程或函数,使用 resident 指示是
            合适的。这个关键字已经被废弃不用了。
    -------------------------------------------------------------------------------}

    { index:属性序号 }

    type
      TMyObject = class(TObject)
      private
        FLeft: Integer;
        FTop: Integer;
        FWidth: Integer;
        FHeight: Integer;
        function GetInfo(const Index: Integer): Longint;
        procedure SetInfo(const Index: Integer; const Value: Longint);
      public
        property iLeft: Longint index 0 read GetInfo write SetInfo;
        property iTop: Longint index 1 read GetInfo write SetInfo;
        property iWidth: Longint index 2 read GetInfo write SetInfo;
        property iHeight: Longint index 3 read GetInfo write SetInfo;
      end;

    function TMyObject.GetInfo(const Index: Integer): Longint;
    begin
      case Index of
        0:
          Result := FLeft;
        1:
          Result := FTop;
        2:
          Result := FWidth;
        3:
          Result :=FHeight;
      end;
    end;

    procedure TMyObject.SetInfo(const Index: Integer; const Value: Longint);
    begin
      case Index of
        0:
          FLeft := Value;
        1:
          FTop := Value;
        2:
          FWidth := Value;
        3:
          FHeight :=Value;
      end;
    end;

    ----------

    { index:属性的多个元素 }

    type
      TMyObject = class(TObject)
      private
        FList: TStringList;
        function GetItem(Index: Integer): string;
        procedure SetItem(Index: Integer; const Value: string);
      public
        constructor Create;
        destructor Destroy; override;
        property Items[Index: Integer]: string read GetItem write SetItem;
      end;

    constructor TMyObject.Create;
    begin
      inherited;
      FList := TStringList.Create;
      FList.Add('星期一');
      FList.Add('星期二');
      FList.Add('星期三');
      FList.Add('星期四');
      FList.Add('星期五');
      FList.Add('星期六');
      FList.Add('星期日');
    end;

    destructor TMyObject.Destroy;
    begin
      FList.Free;
      inherited;
    end;

    function TMyObject.GetItem(Index: Integer): string;
    begin

      if (Index >= 0) and (Index <= (FList.Count - 1)) then
        Result := FList[Index]
      else
        Result := 'Out of Index';
    end;

    procedure TMyObject.SetItem(Index: Integer; const Value: string);
    begin
      if (Index >= 0) and (Index <= (FList.Count - 1)) then
        FList[Index] := Value;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var
      I: Integer;
      MyObj: TMyObject;
    begin
      MyObj := TMyObject.Create;
      try
        Caption := MyObj.Items[2];
        MyObj.Items[2] := 'Wednesday';
        for I := 0 to 6 do
          ShowMessage(MyObj.Items[I]);
      finally
        MyObj.Free;
      end;
    end;

    ----------

    { near }

    function Add(A, B: Integer): Integer; near;
    { 如果这个程序被编译为 Test.exe,并且另一个处于本地的程序需要调用这个函数,可以
      使用以下语句 }
    function Add(A, B: Integer): Integer; stdcall; external 'Test.exe';

    ----------
    { far }

    function Add(a,b: Integer): Integer; far;
    { 如果这个程序被编译为 Test.exe, 并且另一个处于其他计算机的程序需要调用这个函
      数, 可以使用以下语句 }
    function Add(a,b: Integer): Integer; stdcall; external 'Test.exe';

    ----------

    { export }

    function Add(a,b: Integer): Integer; export;
    { 如果这个程序被编译为 Test.exe, 而另一个程序需要调用这个函数,可以使用以下语句 }
    function Add(a,b: Integer): Integer; stdcall; external 'Test.exe';

    ----------

    { exports }

    library Test;

    function TestFunc(I: Integer): string; stdcall;
    begin
      Result := IntToStr(I);
    end;

    exports TestFunc;

    begin

    end.

    { 如果输出的对象被重载,则必须给对象起个别名,并注明参数 }

    library Test;

    function TestFunc(I: Integer): string; overload; stdcall;
    begin
      Result := IntToStr(I); 
    end;

    function TestFunc(S: string): Integer; overload; stdcall;
    begin
      Result := StrToInt(S);
    end;

    exports
      TestFunc(I: Integer) name 'TestFunc1',
      TestFunc(S: string)  name 'TestFunc2';

    begin

    end.

    ----------

    { external }

    {$L Test.OBJ}
    procedure TestFunc(I:Integer); external;

    { 如果是从 dll 或外部程序中引用,则可以使用以下代码 }
    function TestFunc(FileName: string): string; external 'Test.dll';

    { 如果被引用的函数被重载,则必须另外指出引用的名称 }
    function MyFunc1(Code: Integer): string; overload; stdcall; external 'Test.dll' name 'TestFunc1';
    function MyFunc2(Name: string): Integer; overload; stdcall; external 'Test.dll' name 'TestFunc2';

    ----------

    { name }

    function MessageBox(HWnd: Integer; Text, Caption: PChar; Flags: Integer)
      : Integer; stdcall; external 'user32.dll' name 'MessageBoxA';

    ----------

    { resident }

    function Test: string;
    exports Test name 'MyTest' resident;
    编译时会给出警告:Symbol 'RESIDENT' is deprecated



    {-------------------------------------------------------------------------------
      名称:【dispinterface】、【dispid】

      功能:Microsoft 专用。

            dispinterface :用于声明一个特定的适配器接口, 这个适配器能够接受标准系统
            接口中传入传出的数据。用 DispInterface 声明的接口不能被继承,只能够被引
            用。DispInterface 方法只能调用,并且必须被动态绑定。可以通过 DispId 为接
            口内方法分配适配序号。DispInterface 仅能用于 Windows 平台, 如果在 Linux
            下进行开发, 则此关键字会自动被系统屏蔽。

            dispid :DispInterface 接口中,用于指定特定的适配序号。在 DispInterface
            接口中, 适配序号必须是唯一的。如果不指定 DispId,则系统会自动分配适配序号
            给接口内每一个方法,可以通过适配序号访问 DispInterface 接口中的方法。
    -------------------------------------------------------------------------------}

    { dispinterface }

    { 通常情况下,不使用 DispInterface }

    ----------

    { dispid }

    type
      IStringsDisp = dispinterface
        ['{EE05DFE2-5549-11D0-9EA9-0020AF3D82DA}']
        property ControlDefault[Index: Integer]: Olevariant dispid 0; default;
        function Count: Integer; dispid 1;
        property Item[Index: Integer]: Olevariant dispid 2;
        procedure Remove(Index: Integer); dispid 3;
        procedure Clear; dispid 4;
        function Add(Item: Olevariant): Integer; dispid 5;
        function _NewEnum: IUnknown; dispid - 4;
      end;

  • 相关阅读:
    前后端分离基于Oauth2的SSO单点登录怎样做?
    Spring Security基于Oauth2的SSO单点登录怎样做?一个注解搞定
    微服务业务监控和行为分析怎么做?试试日志埋点
    Spring Cloud Gateway的动态路由怎样做?集成Nacos实现很简单
    Spring Cloud异步场景分布式事务怎样做?试试RocketMQ
    Apache RocketMQ 消息队列部署与可视化界面安装
    Spring Cloud同步场景分布式事务怎样做?试试Seata
    实施微服务架构的关键技术
    Spring Cloud开发人员如何解决服务冲突和实例乱窜?(IP实现方案)
    独立博客,从零到千万访问,这三年我都做了什么
  • 原文地址:https://www.cnblogs.com/Chaobs/p/3837569.html
Copyright © 2011-2022 走看看