我可以将泛型变量的类型作为参数传递吗?

时间:2014-07-21 11:47:23

标签: delphi generics

我可以通过声明声明类的类型:

type
  TMyObject = class(TSomething);
  TMyObjectClass = class of TMyObject;

我正在尝试做这样的事情:

IData<TIn,TOut> = interface;
  IData = interface
    function GetGenericData<Tin,TOut>: IData<TInput,TOut>;
    function GetInType: TRttiType;
    function GetOutType: TRttiType;
  end;

声明一个可以访问泛型类型的基类型,并提供有关通用输入和输出类型的信息。

  IData<TIn,TOut> = interface(IData)
    ['{5B402458-22EC-4A8B-83F3-C11AC575B79E}']
    function GetInput(Index: Integer): TIn;
    function GetInputCount: Integer;
    function GetOutput(Index: Integer): TOut;
    function GetOutputCount: Integer;
    property Input[index: integer]: TIn read GetInput;
    property Output[index: integer]: TOut read GetOutput;
    property InputCount: integer read GetInputCount;
    property OutputCount: integer read GetOutputCount;
  end;

这是包含2个数据数组的实际泛型类型。请注意,输入和输出不需要是相同的类型。

然后我有一个包含一个或多个不同类型的IData的类。

TStage = class(TPipelineStage, IData);
TStage<TIn, TOut> = class(TStage, IData<TIn, TOut>);

TMyPipeline = class
  fStages = TArray<TStage>;  <<-- this is really a list of TStage<?,?>

我想在班上列出不同的TStages,但很明显我无法对其进行编码 如何从TStage<IInterfaceA, InterfaceB>访问TStage<InterfaceB, InterfaceB>fStages

我可以在此上下文中使用class of ....并从那里实例化一个对象吗?

我使用这种方法的原因是我在如此声明的Pipeline阶段使用委托:

TDelegate<TIn, TOut> = reference to procedure(const Data: IData<TIn, TOut>);

1 个答案:

答案 0 :(得分:3)

Delphi语言存在一些限制,会阻止您按照您尝试的方式执行操作。拿代码:

IData<TIn,TOut> = interface;
IData = interface
  function GetGenericData<Tin,TOut>: IData<TInput,TOut>;
  function GetInType: TRttiType;
  function GetOutType: TRttiType;
end;

这里有一个接口中的泛型方法。 Delphi(至少在XE3之前)不支持接口中的泛型方法。

在其他snipet中你有:

TStage = class(TPipelineStage, IData);
TStage<TIn, TOut> = class(TStage, IData<TIn, TOut>);

TMyPipeline = class
  fStages = TArray<TStage>;  <<-- this is really a list of TStage<?,?>

代码中问题的答案是。这是一个数组,而不是列表。但是,由于您的数组中包含TStage的实例,因此无论TStage<TIn, TOut>TIn是什么类型,它都会保留TOut的实例,没有任何问题。

你有这个问题:

我想在我的班级中列出不同的TStages,但显然我无法对其进行编码。 如何从fStages访问TStage和TStage?

实际上,你可以!可以声明某个类型的列表(在您的情况下为TStage)并保存降序类的实际实例,甚至是通用子类。

在我看来,您希望一个泛型方法将已经键入的TStage实例返回到降序类型,以避免类型转换和某些类型测试,最终返回nil如果stage是另一个类的实例,对吧?

在这种情况下,泛型方法可能会有所帮助,但仅限于类,而不是接口。我会做这样的事情(我手头没有Delphi来测试代码,但这个想法似乎符合你的需求):

interface

type
  TMyPipeline = class
  private
    FStages: TObjectList<TStage>;
  public
    // Constructors, destructor and other methods...
    function StageAs<TIn, TOut>(aIndex: Integer): TStage<TIn, TOut>;
  end;

implementation

function TMyPipeline.StageAs<TIn, TOut>(aIndex: Integer): TStage<TIn, TOut>;
var
  stage: TStage;
begin
  stage := FStages[aIndex];
  if stage.InheritsFrom(TStage<TIn, TOut>) then
    Result := TStage<TIn, TOut>(stage)
  else
    Result := nil;
end;