Я пытаюсь создать общий предок для составных элементов управления. Первоначальная идея выглядела примерно так:
type
TCompositeControl<TControl1: TControl; TControl2: TControl> = class(TWinControl)
private
FControl1,
FControl2: TControl;
public
constructor Create(AOwner: TComponent); override;
end;
TLabelAndEdit = TCompositeControl<TLabel, TEdit>; // simple example for illustration only
constructor TCompositeControl<TControl1,TControl2>.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FControl1 := TControl1.Create(Self);
FControl2 := TControl2.Create(Self);
end;
Как вы, возможно, уже знаете, это вызовет ошибку компилятора E2568: невозможно создать новый экземпляр без ограничения CONSTRUCTOR в объявлении параметра типа. Однако добавление ограничения constructor
не помогает, поскольку подразумевает конструктор без параметров.
Приведение шаблонов к TControl
делает код компилируемым:
...
FControl1 := TControl(TControl1).Create(Self);
...
... но это приводит к нарушению прав доступа во время выполнения.
Один хак, который, вероятно, сработает, — это вызов конструктора через RTTI, но я бы посчитал это довольно грязным решением.
Другой хак, который по существу работает, использует переменные типа класса в качестве промежуточных звеньев:
type
TControlClass = class of TControl;
constructor TCompositeControl<TControl1,TControl2>.Create(AOwner: TComponent);
var
lCtrlClass1,
lCtrlClass2: TControlClass;
begin
inherited Create(AOwner);
lCtrlClass1 := TControl1;
FControl1 := lCtrlClass1.Create(Self);
lCtrlClass2 := TControl2;
FControl2 := lCtrlClass2.Create(Self);
end;
Есть ли более чистое решение? Кроме того, может ли кто-нибудь объяснить мне, почему ограничения типа класса недостаточно для прямого вызова виртуального конструктора для параметра типа?