"Nested" 在 Delphi 中键入约束

"Nested" type constraints in Delphi

假设我有一个 class

TController<T_Ui: TGui; T_Man: TManager> = class
end;

如果我尝试使用此 class 作为通用过程的约束:

procedure MyProc<T: TController<T_Ui, T_Man>>(ACont: T);

我收到一个错误 undefined identifier T_Ui


有没有比

更短的方法来定义过程
procedure MyProc<T_Ui: TGui; TMan: TManager; T: TController<T_Ui, T_Man>>(ACont: T);

如果我想要的只是对 TController 类型的约束 T?

已编辑:

如果我可以定义:

procedure MyProc<T: TController<*, *>>(ACont: T);

编译器应该清楚一切。

我的问题是,而不是写

MyProc<TMyController>(Cont);

我要写

MyProc<TMyUi, TMyManager, TMyController>(Cont);
procedure MyProc<T: TController<T_Ui, T_Man>>(ACont: T);

让我们考虑一下这意味着什么。这是一个具有一个泛型参数 T 的泛型方法,它是一个必须从 TController<T_Ui, T_Man> 派生的 class。由于 T_UiT_Man 不是泛型参数,编译器必须将它们解释为具体类型。您没有定义该名称的类型,因此出现编译器错误。

但是您当然不希望编译器将 T_UiT_Man 视为具体类型。你的意思是它们是通用参数。在这种情况下,您必须这样声明它们。

procedure MyProc<T_Ui: TGui; TMan: TManager; T: TController<T_Ui, T_Man>>(ACont: T);

或者像这样。

procedure MyProc<T_Ui: TGui; TMan: TManager>(ACont: TController<T_Ui, T_Man>);

通过删除冗余参数T更简单。

本质上,您希望隐式参数化,但这并不存在。必须显式声明通用参数。

现在,有时使用的一种技术是将非泛型 class 声明为泛型 class 的基类型。

type
  TController = class
    ....
  end;

  TController<T_Ui: TGui; T_Man: TManager> = class(TController)
    ....
  end;

然后你可以这样写你的泛型方法:

procedure MyProc<T: TController>(ACont: T);

现在,这种方法要求您可以在 TController 中声明足够的功能。如果 MyProc 需要调用只能在派生自 TController 的泛型 class 中声明的方法,那么这种方法对您没有用。