защо не мога да декларирам общ формуляр

това, което се опитвам да направя, е основно да декларирам форма като тази:

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

компилаторът не обвинява никаква грешка или предупредителни съобщения, ако тази функция е разрешена или не, така или иначе, но когато се опитам да добавя някои контроли в дизайнера, получавам това съобщение

Declaration of class TFormCRUDBase is missing or incorrect.

така че въпросът е защо синтаксисът ми позволява да използвам, а IDE просто ме изрита.

Thx предварително


person kabstergo    schedule 02.02.2015    source източник
comment
Декларацията на класа трябва да бъде затворена с ключова дума end.   -  person Abelisto    schedule 02.02.2015
comment
може би не бях ясен, има още неща, добавени към класа като полета и методи, просто поставих декларацията тук. модифицирах, за да е по-четливо.   -  person kabstergo    schedule 02.02.2015
comment
Както казва Дейвис: Дизайнерът на формуляри не поддържа генерични типове. Но можете да направите wotk arround, като позволите на вашия формуляр да наследи необобщен клас. Мога да направя решение за вас, ако искате   -  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
мога да се съглася с факта, че решиха да поставят effors другаде, изобщо не съм съгласен е несъответствието между компилатор x 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 има пълна поддръжка за generic, това наистина е за аргумента 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: Това не е толкова удобство (което предполага мързел), но често просто не си струва да се внедри това, защото може да отнеме много време и/или едва ли има търсене. С други думи, често е солидно бизнес решение да не правиш всичко възможно, а да правиш само това, което има (бизнес) смисъл. Помислете за YAGNI. - 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