Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Конструктор Create 
:(
    Опции темы
omickron
Дата 25.8.2011, 19:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 12.2.2009

Репутация: нет
Всего: 1



Ребят, помогите, пожалуйста, разобраться с пониманием работы конструкторов.

Имеется форма класса TMyForm = class(TForm).
Как создать объект её типа?
Код

Form := TMyForm.Create(Owner);


Тут всё просто.

Я задался мыслью проверить, а не существует ли уже форма такого класса? Т.е. я хочу, чтобы в моём приложении форма класса TMyForm была только в одном экземпляре.

Я сделал глобальную переменную Forms класса-наследника TStringList, в которой храню имена типов форм и ссылки на сами экземпляры форм.
В конструкторе TMyForm я складываю форму в список, в деструкторе - выбрасываю из списка.

Таким образом конструктор формы TMyForm получается таким:
Код

constructor TForm.Create(AOwner: TComponent)
begin
  inherited Create(AOwner);
  Forms.AddObject(ClassName, Self);
end;


В деструктор - вставил удаление объекта из списка.

А теперь нужно в конструктор вставить проверку, не существует ли уже такой формы. Получаем:

Код

constructor TForm.Create(AOwner: TComponent)
begin
  if Forms.IndexOf(ClassName) >= 0 then
    begin
      //Что написать здесь, чтобы вызов Form := TMyForm.Create(Owner); вернул в Form не новый объект, а уже существующий?
    end
  else 
    begin
      inherited Create(AOwner);
      Forms.AddObject(ClassName, Self);
    end;
end;


P.S. В принципе, формы тут только для примера. На деле, у TMyForm ещё куча наследников, поэтому складывать в список имя класса нормально. Там могут быть и TMyDrawForm, и TMySimpleForm, и т.п. И каждая из них должна быть уникальна.
Вместо форм, на самом деле, можно использовать любые объекты, не обязательно визуальные.

Итого, главный вопрос: как в конструкторе проверить что-либо и вместо нового объекта вернуть другой?
PM MAIL   Вверх
rodnover
Дата 25.8.2011, 20:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 223
Регистрация: 7.4.2009

Репутация: нет
Всего: 10



Сделать конструктор приватным и использовать классовую функцию. Шаблон называется singleton

PM MAIL   Вверх
bems
Дата 25.8.2011, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Цитата(rodnover @  25.8.2011,  20:04 Найти цитируемый пост)
Сделать конструктор приватным

толку в этом мало. Просто не вызывать его напрямую.


--------------------
Обижено школьников: 8
PM MAIL   Вверх
omickron
Дата 26.8.2011, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 12.2.2009

Репутация: нет
Всего: 1



Цитата(rodnover @  25.8.2011,  20:04 Найти цитируемый пост)
Сделать конструктор приватным и использовать классовую функцию.

Ага, понял. Правда, для TForm это не прокатит - там виртуальный конструктор уже описан в public.

Цитата(bems @  25.8.2011,  21:35 Найти цитируемый пост)
толку в этом мало.

Ну почему мало? Если конструктор будет приватным, его вызвать не получится. И для создания объектов придётся использовать или классовую функцию, или фабрику.
PM MAIL   Вверх
superVad
Дата 26.8.2011, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 735
Регистрация: 6.4.2006
Где: Черкассы, Украина

Репутация: 4
Всего: 15



omickron, а может лучше так спроектировать интерфейс программы, что бы просто нельзя было одну форму 2 раза вызвать?
PM MAIL   Вверх
bems
Дата 26.8.2011, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Цитата(omickron @  26.8.2011,  09:26 Найти цитируемый пост)
Если конструктор будет приватным, его вызвать не получится.
всегда для любого класса можно вызвать публичный конструктор унаследованный от TObject

Это сообщение отредактировал(а) bems - 26.8.2011, 14:08


--------------------
Обижено школьников: 8
PM MAIL   Вверх
sCreator
Дата 27.8.2011, 11:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 84
Регистрация: 20.8.2009
Где: Московская област ь

Репутация: 2
Всего: 5



Где то так
Код

unit UCustomSingleForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TCustomSingleForm = class(TForm)
  private
    FIsDestroing: Boolean;
    FIsCreating: Boolean;
    function CheckDestroing(): Boolean;
    { Private declarations }
  protected
    property IsDestroing: Boolean read FIsDestroing;
    property IsCreating: Boolean read FIsCreating;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    // constructor CreateNew(AOwner: TComponent; Dummy: Integer  = 0); virtual;
    destructor Destroy; override;

    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
    procedure DestroyForce;
    procedure FreeInstance; override;
    class function NewInstance: TObject; override;
    // class function
  end;

implementation

{ TCustomSingleForm }

procedure TCustomSingleForm.AfterConstruction;
begin
  if IsCreating then
    inherited AfterConstruction();
  FIsCreating := false;
end;

procedure TCustomSingleForm.BeforeDestruction;
begin
  if CheckDestroing then
    inherited BeforeDestruction();
end;

constructor TCustomSingleForm.Create(AOwner: TComponent);
begin
  if IsCreating then
    inherited Create(Application);
end;

destructor TCustomSingleForm.Destroy;
begin
  if IsDestroing then
    inherited Destroy();
end;

procedure TCustomSingleForm.DestroyForce;
begin
  if CheckDestroing() then
    exit;
  FIsDestroing := true;
  Destroy();
end;

procedure TCustomSingleForm.FreeInstance;
begin
  if IsDestroing then
    inherited;
end;

class function TCustomSingleForm.NewInstance: TObject;
var
  i: Integer;
begin
  for i := 0 to Application.ComponentCount - 1 do
    if Application.Components[i].ClassInfo = Self.ClassInfo then
    begin
      Result := Application.Components[i];
      exit;
    end;

  Result := inherited NewInstance();
  TCustomSingleForm(Result).FIsCreating := true;
end;

function TCustomSingleForm.CheckDestroing(): Boolean;
begin
  if (csDestroying in ComponentState) then
    FIsDestroing := true;
  Result := FIsDestroing;
end;

end.


Присоединённый файл ( Кол-во скачиваний: 1 )
Присоединённый файл  SinglTest.zip 3,74 Kb
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0501 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.