почему я не могу объявить общую форму

то, что я пытаюсь сделать, это в основном объявить такую ​​​​форму:

TFormCRUDBase<T : class> = class(TFormLayoutBase, MVP.Intf.CRUD.ICRUDView<T>)
{ ... }
end;

в любом случае компилятор не обвиняет в каких-либо сообщениях об ошибках или предупреждениях, разрешена эта функция или нет, но когда я пытаюсь добавить некоторые элементы управления в дизайнере, я получаю это сообщение

Declaration of class TFormCRUDBase is missing or incorrect.

поэтому вопрос в том, почему синтаксис позволяет мне использовать, а IDE меня просто выкидывает.

спасибо заранее


person kabstergo    schedule 02.02.2015    source источник
comment
Объявление класса должно быть закрыто ключевым словом end.   -  person Abelisto    schedule 02.02.2015
comment
может быть, я не ясно выразился, в класс добавлено больше вещей, таких как поля и методы, я просто поместил это объявление здесь. я изменил, так что это может быть более разборчивым.   -  person kabstergo    schedule 02.02.2015
comment
Как говорит Дэвис: Дизайнер форм не поддерживает универсальные типы. Но вы можете сделать так, чтобы ваша форма наследовала не универсальный класс. Я могу сделать решение для вас, если вы хотите   -  person Jens Borrisholt    schedule 03.02.2015
comment
@JensBorrisholt да, не могли бы вы уточнить?   -  person kabstergo    schedule 03.02.2015


Ответы (2)


Проще говоря, дизайнер форм не поддерживает универсальные типы.

Компилятор отлично работает с универсальными типами. Вы можете создать пользовательский интерфейс, добавить элементы управления и т. д. с кодом времени выполнения. Но дизайнер форм не поддерживает универсальные типы.

person David Heffernan    schedule 02.02.2015
comment
Боже мой, это так расстраивает, иногда я действительно не могу понять Delphi. почему они предоставляют такую ​​функцию синтаксически, но не обрабатывают изменения, которые необходимо внести в IDE, чтобы такая функция была совместима. - person kabstergo; 02.02.2015
comment
Ну, я предполагаю, что дизайнеры считают, что потомки TForm не являются главными кандидатами на использование дженериков. Что, наверное, разумно. Я полагаю, что для того, чтобы файлы .dfm поддерживали универсальность, потребовалось бы немало работы. Я утверждаю, что дизайнеры взвесили все за и против и решили приложить усилия в другом месте. Разочарование для вас. - person David Heffernan; 02.02.2015
comment
я могу согласиться с тем, что они решили приложить усилия в другом месте, я совершенно не согласен, это несоответствие между компилятором и IDE, я имею в виду, что в этом случае IDE должна предупредить меня, что это не разрешено или не поддерживается и не бросить какое-то расплывчатое общее исключение. так что, в конце концов, у меня есть компилятор, говорящий, что все в порядке, а с другой стороны, IDE, говорящая, что это не так. - person kabstergo; 02.02.2015
comment
Я предполагаю, что дизайнеры сказали бы, что IDE никогда не будет генерировать код .pas для универсальной формы. Вы пошли и изменили сгенерированный IDE код формы. Это, вероятно, аргумент, который они сделают. Я догадываюсь. Было бы полезно, если бы IDE просто дала вам окончательное сообщение о том, что дженерики не поддерживаются. Тогда бы вы знали и не тратили время на то, чтобы заставить его работать. - person David Heffernan; 02.02.2015
comment
да, очень помогло бы. в любом случае спасибо за помощь и обсуждение - person kabstergo; 02.02.2015
comment
Я предполагаю, что тот факт, что IDE использует RTTI для получения информации о классах и отображения значений, также играет роль. RTTI для универсального типа не так просто, - person Rudy Velthuis; 02.02.2015
comment
@RudyVelthuis Так ли это? Насколько мне известно, дженерики хорошо поддерживаются RTTI. - person David Heffernan; 02.02.2015
comment
Хммм... Помню, у меня были серьезные проблемы. - person Rudy Velthuis; 02.02.2015
comment
@RudyVelthuis, я должен согласиться с Дэвидом, RTTI полностью поддерживает общий, это действительно касается аргумента BY DESIGN, мне действительно не нравится это предложение, потому что оно обычно используется разработчиками, когда они не хотят помещать необходимое попытки заставить что-то работать. как сказал Дэвид, возможно, изменения, которые им нужно внести в их поддержку dfm, будут огромными. - person kabstergo; 03.02.2015
comment
@kabstergo - используется разработчиками, когда они не хотят, скорее всего, неправильно. Профессиональная разработка программного обеспечения — это не то, что происходит по прихоти какого-то случайного разработчика. В этом случае я подозреваю, что не так много клиентов просили о поддержке дженериков в формах в дизайнере IDE... - person Leonardo Herrera; 04.02.2015
comment
@LeonardoHerrera Я не намекал, что именно это произошло в данном конкретном случае, мой аргумент здесь в том, что по замыслу иногда бывает удобно. - person kabstergo; 04.02.2015
comment
@kabstergo: Дело не столько в удобстве (подразумевается лень), сколько в реализации этого часто просто не окупается, потому что это может занять много времени и/или вряд ли будет востребовано. Другими словами, часто бывает разумным деловым решением не делать все возможное, а делать только то, что имеет смысл (для бизнеса). Подумайте о ЯГНИ. - person Rudy Velthuis; 04.02.2015
comment
@LeonardoHerrera, я согласен со всем, что вы сказали, просто не так просто справиться с ограничениями дизайна на протяжении многих лет. Я не могу сосчитать, сколько раз мы попадаем лицом в эти стены - person kabstergo; 04.02.2015

Вы просили работу вокруг. Решение простое, но не элегантное. Вы должны сделать класс сильного типа, и вы получите унаследованную от него форму.

Сначала я делаю несколько фиктивных типов:

type
  ICRUDView<T> = Interface
   function GetObject : T;
  end;

  TMyObject = class
    function Time: String;
  end;

и простая реализация:

{ TMyObject }

function TMyObject.Time: String;
begin
  Result := TimeToStr(now);
end;

procedure TForm5.FormCreate(Sender: TObject);
begin
  Caption := Self.GetObject.Time;
end;

Затем сильный тип, от которого вы должны наследоваться:

type
  TMyClassForm = class(TForm, ICRUDView<TMyObject>)
  strict private
    InternalObject: TMyObject;
  public
    function GetObject: TMyObject;
  end;

и его реализация:

{ TMyClassForm }

function TMyClassForm.GetObject: TMyObject;
begin
  if (InternalObject = nil) then
    InternalObject := TMyObject.Create;

  Result := InternalObject;
end;

Наконец, вы делаете свою форму унаследованной от вашего вновь созданного класса:

  TForm5 = class(TMyClassForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

и использовать его в своей форме

procedure TForm5.FormCreate(Sender: TObject);
begin
  Caption := Self.GetObject.Time;
end;

Это работает, но не элегантно!

person Jens Borrisholt    schedule 03.02.2015