Delphi - Создать экземпляр подкласса - PullRequest
0 голосов
/ 22 августа 2010

У меня есть класс, определенный как:

TfraFrame = class(TFrame);

, тогда у меня есть несколько подклассов, все наследующие от него, такие как:

TfraUsers = class(TfraFrame);
TfraGroups = class(TfraFrame);
TfraMenus = class(TfraFrame);

В моей основной форме я объявил переменные как:

var
  fraUsers: TfraUsers;
  fraGroups: TfraGroups;
  fraMenus: TfraMenus;

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

Я хотел бы передать переменную следующим образом:

procedure ShowFrame(Frame: TfraFrame)
begin
  if Frame = nil then
  begin
    Frame := TfraFrame.Create(self);
    Frame.Init(Panel1);
  end;

  Frame.Show;
end;

иназовите это так:

ShowFrame(fraUsers);

Я ожидал, что это создаст экземпляр TfraUsers (потому что это то, что fraUsers объявлено как), однако, я подозреваю, что это может быть создание экземпляраfraFrame.

Есть ли способ создать экземпляр типа, который был объявлен как переменная?

Ответы [ 2 ]

3 голосов
/ 22 августа 2010

Да, вам нужно указать showFrame, какой класс создавать:

добавить

type
  tfraFrameClass = class of TfraFrame;

сразу после объявления tfraFrame. И измените showFrame на:

function ShowFrame(Frame: TfraFrame; FrameClass: TfraFrameClass): TfraFrame;
begin
  if Frame = nil then
  begin
    Result := FrameClass.Create(self);
    Result.Init(Panel1);
  end
  else
    Result := Frame;

  Result.Show;
end;

Обратите внимание, что вы не можете передать Frame как параметр var, так как компилятор будет настаивать на том, чтобы объявленные и фактические типы переданного параметра были точно такими же.

Обновление Обновлен пример отображения кадра, когда он уже был назначен.

Обновление Я не упомянул, что присвоение результата вызова Create в коде OP для процедуры showFrame не будет работать. Если бы оно не было объявлено как var, присваивание не выходило бы за рамки процедуры showFrame, значение переменной, переданной в showFrame, не изменилось бы. Объявление его как var не будет работать, как указано выше. Решение состоит в том, чтобы сделать то, что предлагает @Andreas: использовать нетипизированный указатель; или сделайте это функцией, как я сделал. Конечно (с улыбкой) я предпочитаю мой, так как он немного лучше сохраняет безопасность типов.

Также, конечно, в моем примере предполагалось, что результат функции showFrame будет присвоен соответствующей переменной кадра, например:

fraUsers := showFrame(fraUsers, TfraUsers);

Обновление Или, как указал Sertac, вы все равно можете использовать процедуру с параметром var, когда выполняете приведение к переменной, передаваемой в showForm.

procedure showFrame(var Frame: TfraFrame; FrameClasse: TfraFrameClass);
begin
  if Frame = nil then
  begin
    Frame := FrameClass.Create(self);
    Frame.Init(Panel1);
  end;

  Frame.Show;
end;

и назовите его так:

showFrame(TfraFrame(fraUsers), TFraUsers);
0 голосов
/ 23 августа 2010

Я предлагаю вам сделать свойства переменных вашего кадра

property fraUsers: TfraUsers read GetfraUsers write ffraUsers;
..

function GetFraUsers: TFraUsers;
begin
  if fFraUsers = nil then
     fFraUsers := TfraUsers.Create(...);
  Result := ffraUsers;
end;

Then

procedure ShowFrame(Frame: TfraFrame)
begin
  Frame.Init(Panel1);
  Frame.Show;
end;

procedure form1.Button1Click(...)
begin
  ShowFrame(fraUsers); // creates the frame if it does not exist
end;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...