Delphi中的泛型帮助器类

时间:2018-08-25 18:50:42

标签: delphi generics helper

我有一对必须互为引用的类A和B。这意味着A的接口use子句必须提及B的单位,B的interface use子句必须提及A的单位。这是Delphi中的循环引用,不允许使用。我正在使用here找到的方法来解决圆度问题。基本上,A对B的引用按预期方式存在,但是B对A的引用降级为TObject引用,并且B使用帮助程序类将对A的引用转换为正确的类型。以下是代码片段,以说明问题:

unit A;

interface

uses
    B;

type
    TA = class(TObject)
    public
        Name: string;
        B: TB;
    end;

implementation

end.

unit B;

interface

type
    TB = class(TObject)
    public
        Name: string;
    protected
        fA: TObject;
    end;

implementation

end.

unit BHelper;

interface

uses
    A,
    B;

type
    TBHelper = class helper for TB
    private
        function GetA: TA;
        procedure SetA(Value: TA);
    public
        property A: TA read GetA write SetA;
    end;

implementation

function TBHelper.GetA: TA;
begin
    Result := TA(fA);
end;

procedure TBHelper.SetA(Value: TA);
begin
    fA := a;
end;

end.

我实际上有几对此类。那是很多帮助类,他们都在做同样的事情。因此,我尝试编写一个通用的帮助程序类,该类可以通过参数设置来帮助B类:

unit GenericHelper;

interface

uses
    A,
    B;

type
    TGenericHelper<T1, T2> = class helper for T2  //Error: Type parameters not allowed
    private
        function GetA: T1;
        procedure SetA(Value: T1);
    public
        property A: T1 read GetA write SetA;
    end;

implementation

function TGenericHelper<T1, T2>.GetA: T1;
begin
    Result := T1(fA);  //Error: undeclared parameter fA
end;

procedure TGenericHelper<T1, T2>.SetA(Value: T1);
begin
    fA := a;  //Error: undeclared parameter fA
end;

end.

我的问题是,我对泛型类了解不足,无法确定这是否有效。我不知道如何解决代码中显示的错误。

有没有办法做到这一点?

全面披露:实际情况比这还丰富。这些对以层次结构排列,如ABCD,其中A持有对B的引用,B持有对A和C的引用,C持有对B和D的引用,D持有对C的引用。这些是一对多的关系A实际持有B的列表,每个B持有C的列表,每个C持有D的列表。理想的解决方案不会排除这些关系。我也更喜欢每单元一个类,而不是将相关类组合成一个单元。

谢谢

1 个答案:

答案 0 :(得分:0)

这个错误很明显

 TGenericHelper<T1, T2> = class helper for T2  //Error: Type parameters not allowed

您不能使用这样的泛型。原因很明显,因为您的实现尝试在实例化泛型类之前使访问属于特定类的变量(使实现变为非泛型)。

最简单的方法是将A / B(和C / D等)放在一个单元中,并只对类使用正向声明。

unit ABCD;

interface

    TB = class;
    TC = class;
    TD = class;

    TA = class(TObject)
      public
        B: TB;
        C: TC;
    end;

    TB = class(TObject)
       public
         A: TA;
    end;

    TC = class(TObject)
      public
        B : TB;
        D : TD;
    end;

    TD = class(TObject)
      public
        A: TA;
        C: TC;
    end;

implementation

end.