【问题标题】:Delphi: A generic list of generic-descendants and taking a generic as a parameterDelphi:泛型后代的泛型列表并将泛型作为参数
【发布时间】:2009-10-27 18:49:03
【问题描述】:

我对泛型的理解以及如何使用和如何使用泛型有点挣扎。

我有一个像这样的通用类 TControlMediator:

TControlMediator<C, T> = class
private
  FMediatedComponent: C;
public
  constructor Create(ComponentToMediate: C);

  function GetValue: T; virtual; abstract;
  procedure SetValue(Value: T); virtual; abstract;

  property MediatedControl: C read FMediatedComponent;
end;

然后,我为每个要调解的控件类型创建“具体”子类:

TEditMediator = class(TControlMediator<TEdit, string>)
public
  function GetValue: string; override;
  procedure SetValue(Value: string); override;
end;

到目前为止,一切似乎都正常。但是,当我想要一个 TControlMediator 后代列表或将 TControlMediator 作为方法的参数时,就会出现问题:

TViewMediator = class
private
  FControlMediators: TList<TControlMEdiator<C, T>>;
public
  procedure registerMediator(AControlMediator: TControlMediator<C, T>);
  procedure unregisterMediator(AControlMediator: TControlMediator<C, T>);
end;

编译器因致命错误而停止:

[DCC Error] mediator.pas(23): E2003 Undeclared identifier: 'C'
[DCC Error] mediator.pas(28): E2007 Constant or type identifier expected

有人知道这应该怎么做吗?

【问题讨论】:

    标签: delphi generics delphi-2010


    【解决方案1】:

    Delphi 在其泛型类型上没有协变或逆变。您的泛型类型必须使用实际类型作为参数。换句话说,这是:

    TViewMediator = class
    private
      FControlMediators: TList<TControlMEdiator<C, T>>;
    public
      procedure registerMediator(AControlMediator: TControlMediator<C, T>);
      procedure unregisterMediator(AControlMediator: TControlMediator<C, T>);
    end;
    

    ...不起作用,因为 C 和 T 不是 TViewMediator 或实际类型的泛型类型参数。

    TControlMediator&lt;TEdit, string&gt; 是一种类型。 TList&lt;TControlMEdiator&lt;C, T&gt;&gt;,当范围内没有类型时,CT 不是类型。您不能在泛型类型的实例化 中使用泛型类型占位符,除非这些占位符在范围内作为包含泛型类型或方法的泛型参数。

    【讨论】:

    • 那么我基本上完蛋了?我的列表必须是一个很好的旧 TList 的 TObjects,并且没有办法将其中的对象转换为 TControlMediator 以便我可以调用它的方法?
    • 在我完全理解你为什么要这样做之前,我不能说你是否被搞砸了。你可以参数化为TViewMediator&lt;C, T&gt; 吗?
    • 我想注册不同类型的中介,例如: MyViewMediator.RegisterMediator(TEditMediator.create(someEdit)); MyViewMediator.RegisterMediator(TComboMediator.create(someCombo));稍后,我想循环所有注册的中介并在它们上调用一个方法。
    • 你可以给你的泛型类型一个非泛型的父类型,并让你的列表成为一个列表。
    • 是的,这就是我的解决方案。甚至可能是一个界面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多