加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 在pascal中动态分配匿名通用函数

发布时间:2020-12-15 09:23:06 所属栏目:大数据 来源:网络整理
导读:我有以下类层次结构 我希望能够动态地分配对TB和TC两种类型的对象进行操作的匿名方法. 所以这是一个简单的人为例子: unit Unit1;interfaceuses Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,
我有以下类层次结构

我希望能够动态地分配对TB和TC两种类型的对象进行操作的匿名方法.

所以这是一个简单的人为例子:

unit Unit1;

interface

uses
  Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TNotifyEventWrapper = class
    private
      FProc: TProc<TObject>;
    public
      constructor Create(Proc: TProc<TObject>);
    published
      procedure Event(Sender: TObject);
    end;

  IA = interface
    procedure Foo;
  end;

  TA = class(TInterfacedObject)
    procedure Foo;
  end;

  TB = class(TA,IA)
    procedure Foo;
  end;

  TC = class(TA,IA)
    procedure Foo;
  end;

  TControl = class
    strict private
    public
    class var NEW : TNotifyEventWrapper;
    class var Foo : TNotifyEvent;
    class function GetWrapper<T:TA,IA,constructor>(D: T): TNotifyEventWrapper;
    class procedure AssignFooHandler<T:TA,constructor>;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TC.Foo;
begin
    ShowMessage('TC.Foo');
end;

class function TControl.GetWrapper<T>(D: T): TNotifyEventWrapper;
begin
    Result :=
    TNotifyEventWrapper.Create
    (
        procedure (S : TObject)
        begin
            T(D).Foo;
        end
    );
end;

class procedure TControl.AssignFooHandler<T>;
var
    X : T;
begin
    X := T.Create;
    try
        TControl.NEW := TControl.GetWrapper<T>(X);

        TControl.Foo := TControl.NEW.Event;

    finally
        FreeAndNil(X);
    end;
end;

procedure TA.Foo;
begin
    ShowMessage('TA.Foo');
end;

procedure TB.Foo;
begin
    ShowMessage('TB.Foo');
end;

constructor TNotifyEventWrapper.Create(Proc: TProc<TObject>);
begin
    inherited Create;
    FProc := Proc;
end;

procedure TNotifyEventWrapper.Event(Sender: TObject);
begin
    FProc(Sender);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
    TControl.Foo(Sender);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
    TControl.AssignFooHandler<TC>;  //TB
end;

end.

我想能打电话

TControl.AssignFooHandler< TC取代;

并拥有TControl.Foo(发件人);方法调用TC.Foo

我也想要TControl.AssignFooHandler< TB&gt ;;导致TControl.Foo(发件人);调用TB.Foo 不幸的是,当我运行它时,它总是调用基类方法TA.Foo. 我不知道怎么解决这个问题.

解决方法

您的Generic被限制为TA和IA的后代. TA.Foo未声明为虚拟,而T(B | C).Foo()未声明为覆盖它.这就是每次调用TA.Foo()的原因.你需要使TA.Foo()虚拟和T(B | C).Foo覆盖它,然后T(B / C).Foo将按预期调用.

此外,在TControl.Foo()有机会调用该对象的Foo()方法之前,您正在释放传递给TControl.GetWrapper()的T(A / B / C)对象.在这个特定的例子中,没关系,因为没有一个Foo()方法访问任何对象成员字段,但是一旦你在实际的生产代码中开始这样做,它很可能会崩溃.在完成使用TNotifyEventWrapper对象之前,需要保持T(A / B / C)对象处于活动状态.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读