zoukankan      html  css  js  c++  java
  • Delphi 中的 procedure of object

    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;
  • 相关阅读:
    Visual Studio各版本区别
    调试ASP.NET网站IIS环境问题解决方法汇总
    关于Webpage Not Found问题解决~~~
    SpringCloud+vue搭建的商城项目
    springcloud实现限流
    ReentrantLock
    栈和堆的特点
    你用对锁了吗?浅谈 Java “锁” 事
    ReentrantReadWriteLock读写锁的使用
    OAuth2
  • 原文地址:https://www.cnblogs.com/marklove/p/9206788.html
Copyright © 2011-2022 走看看