1. 程式人生 > >Delphi 中的 procedure of object

Delphi 中的 procedure of object

定義 fun present value 類型 兼容 only new tno

delphi中經常見到以下兩種定義

Type

TMouseProc = procedure (X,Y:integer);

TMouseEvent = procedure (X,Y:integer) of Object;

兩者樣子差不多但實際意義卻不一樣,

TMouseProc只是單一的函數指針類型;

TMouseEvent是對象的函數指針,也就是對象/類的函數/方法

區別在於類方法存在一個隱藏參數self,也就是說兩者形參不一樣,所以不能相互轉換。

這也就是為什麽delphi中可以這樣賦值 button1.onClick:=button2.onClick;

卻不能這樣賦值 button1.onclick
=buttonclick; (buttonclick為本地函數,button2.onclick為類方法)的原因! 方法類型定義:TMethod = procedure of object; Procedural types allow you to treat procedures and functions as values that can be assigned to variables or passed to other procedures and functions. For example, suppose you define a function called Calc that takes two integer parameters and
returns an integer: function Calc(X,Y: Integer): Integer; You can assign the Calc function to the variable F: var F: function(X,Y: Integer): Integer; F := Calc; If you take any procedure or function heading and remove the identifier after the word procedure or function, what’s left is the name of
a procedural type. You can use such type names directly in variable declarations (as in the example above) or to declare new types: Type TIntegerFunction = function: Integer; TProcedure = procedure; TStrProc = procedure(const S: string); TMathFunc = function(X: Double): Double; Var F: TIntegerFunction;{ F is a parameterless function that returns an integer } Proc: TProcedure; { Proc is a parameterless procedure } SP: TStrProc; { SP is a procedure that takes a string parameter } M: TMathFunc; { M is a function that takes a Double (real) parameterand returns a Double } procedure FuncProc(P: TIntegerFunction); { FuncProc is a procedure whose only parameter is a parameterless integer-valued function } The variables above are all procedure pointers—that is, pointers to the address of a procedure or function. If you want to reference a method of an instance object (see Classes and objects), you need to add the words of object to the procedural type name. For example Type TMethod = procedure of object; TNotifyEvent = procedure(Sender: TObject) of object; These types represent method pointers. A method pointer is really a pair of pointers; the first stores the address of a method, and the second stores a reference to the object the method belongs to. Given the declarations Type TNotifyEvent = procedure(Sender: TObject) of object; TMainForm = class(TForm) procedure ButtonClick(Sender: TObject); ... end; var MainForm: TMainForm; OnClick: TNotifyEvent we could make the following assignment.OnClick := MainForm.ButtonClick; Two procedural types are compatible if they have the same calling convention,the same return value (or no return value), and the same number of parameters, with identically typed parameters in corresponding positions. (Parameter names do not matter.) Procedure pointer types are always incompatible with method pointer types. The value nil can be assigned to any procedural type. Nested procedures and functions (routines declared within other routines) cannot be used as procedural values, nor can predefined procedures and functions. If you want to use a predefined routine like Length as a procedural value, write a wrapper for it: function FLength(S: string): Integer; begin Result := Length(S); end;

理解 Delphi 的類(十) - 深入方法[26] - 回調函數

/把一個方法當作另一個方法的參數, 就是回調方法, 大家習慣稱作回調函數

type
  TFunType = function(i: Integer): Integer; {聲明一個方法類型}

function MyFun(i: Integer): Integer;        {建立類型兼容的函數}
begin
  Result := i*2;
end;

{把函數當作參數, 再定義一個函數}
function MyTest(x: Integer; F: TFunType): Integer;
begin
  Result := F(x);
end;


{測試}
procedure TForm1.Button1Click(Sender: TObject);
var
  Fun: TFunType; {聲明一個 TFunType 的變量}
  i: Integer;
begin
  Fun := MyFun;  {讓方法變量 Fun 指向和它類型兼容的一個方法}

  {測試 Fun; Fun 是一個方法變量, 現在去執行那個方法, 它就可以當作那個方法來使用了}
  i := Fun(4);
  ShowMessage(IntToStr(i));  //8

  {把 Fun 當作參數使用; 把函數當作參數使用, 這就是回調函數}
  i := MyTest(4,Fun);
  ShowMessage(IntToStr(i));  //8
end;

Delphi 中的 procedure of object