(轉)Delphi關鍵字和保留字


分類整理 Delphi 中的“關鍵字”和“保留字”,方便查詢

“關鍵字”和“保留字”不做區分,一共 107 個。



{-------------------------------------------------------------------------------
  名稱:【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: stringname '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;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM