【问题标题】:How to assign an "of object" procedure to a "reference to" procedure?如何将“对象”过程分配给“引用”过程?
【发布时间】:2021-12-01 12:09:34
【问题描述】:

我有:

  TMyProc = reference to procedure(const adata: String);

  TMyObject = Class(Tobject)
  private
    FMyProc: TMyProc ;
  public
    Property MyProc: TMyProc read FMyProc write FMyProc;
  end;

  TAnObject = Class(Tobject)
  public
    procedure MyProcImpl(const adata: integer); overload;
    procedure MyProcImpl(const adata: String); overload;
  end;

我想做类似的事情

   MyObject.MyProc := AnObject.MyProcImpl;

但我得到Incompatible types: 'TMyProc' and 'Procedure of object'。我该怎么办?

【问题讨论】:

  • 哦,是的,编辑有点改变了问题!这就是为什么您应该为此类问题添加minimal reproducible example。如果你做了一个,你就会意识到你原来的问题是不正确的。在 10k 代表你现在应该知道这一点。请注意这一点。
  • 对不起@DavidHeffernan :( 我发布问题太快了我的错 :(
  • 只能将事件方法添加到匿名方法变量(当然也可以是匿名方法)
  • @delphi 我不太明白那句话。您不会向匿名方法变量添加任何内容。你分配他们。您可以分配标准程序,即不是方法。事件方法不是一回事。事件不是语言的一部分。事件只是对象方法类型的属性的约定。

标签: delphi


【解决方案1】:

问题在于重载引入的歧义。如果没有重载,您的代码将可以正常工作。

您可以使用一个临时变量来消除重载的歧义,该变量的类型与您要选择的重载相匹配:

program SO70183946;

type
  TMyProc = reference to procedure(const adata: string);
  TMyProcOfObject = procedure(const adata: string) of object;

  TMyObject = class
  private
    FMyProc: TMyProc;
  public
    property MyProc: TMyProc read FMyProc write FMyProc;
  end;

  TAnObject = class
  public
    procedure MyProcImpl(const adata: integer); overload;
    procedure MyProcImpl(const adata: string); overload;
  end;

procedure TAnObject.MyProcImpl(const adata: integer);
begin
end;

procedure TAnObject.MyProcImpl(const adata: string);
begin
end;

var
  MyObject: TMyObject;
  AnObject: TAnObject;
  MyProcOfObject: TMyProcOfObject;

begin
  MyProcOfObject := AnObject.MyProcImpl;
  MyObject.MyProc := MyProcOfObject;
end.

解决这个问题的另一种方法是显式写出匿名方法,而不是依赖编译器在后台生成它:

MyObject.MyProc :=
  procedure(const adata: string)
  begin
    AnObject.MyProcImpl(adata);
  end;

【讨论】:

  • 感谢@davidHeffernan,另一种选择是声明过程 MyProcImpl(const adata: string);超载;在过程 MyProcImpl(const adata: integer);超载;
  • 有趣的是,不能将类型定义为“对对象的过程(const adata:字符串)的引用;” (这是编译器错误)。乍一看,这样的定义似乎是有道理的。因为没有“对象”部分,如何捕获 Self 以便稍后在实际调用/运行过程时引用它?闭包捕获变量 MyProcOfObject 并包含 Self(数据)指针这一事实是否节省了时间?还是由于 Delphi 错误而编译?结合最后两行是一个错误:MyObject.MyProc := AnObject.MyProcImpl;
  • @MatthiasB 编译器将MyObject.MyProc := MyProcOfObject; 实现为MyObject.MyProc := procedure(const adata: string) begin MyProcOfObject(adata); end; 并捕获包含实例的MyProcOfObject
  • 确实,这解释了它为什么起作用 - 谢谢!但是为什么这不能很好地工作(如果语法允许的话)? MyObject.MyProc := AnObject.MyProcImpl; 将被实现为 MyObject.MyProc := procedure(const adata: string) begin AnObject.MyProcImpl(adata); end; 它将捕获 AnObject。编辑:啊,我现在自己看到了。调用它不会调用对象方法。它仍在调用常规程序。实际上,这一切都说得通。
  • @MatthiasB 是的,这是一个很好的观点,我已将其添加到答案中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-17
  • 1970-01-01
相关资源
最近更新 更多