Как правильно работать с динамическим количеством классов ?

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Ответить
nic1982
новенький
Сообщения: 48
Зарегистрирован: 17.05.2011 16:34:05

Как правильно работать с динамическим количеством классов ?

Сообщение nic1982 »

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

Абстрактный смысл такой:
есть фирма - программа;
есть директор - обработчик нажатия кнопки в программе;
есть менеджер подчиненный директору - TMyDynArrayClass;
есть работник подчиненный менеджеру - TMyClass.
Директор не общается с работником.

Правильно ли я поступаю с динамическим количеством классов ?
Какие есть еще варианты ?

Пример:

Код: Выделить всё

TMyClass = class
  private   
    str : string;
  public
    procedure write_str(tmp : string);
    function  read_str : string;
end;

procedure TMyClass.write_str(tmp : string);
begin
  str:= tmp;
end;

function TMyClass.read_str : string;
begin
  result:= str;
end;


Код: Выделить всё

TMyDynArrayClass = class
  private
    DynArrayClass : array of TMyClass; // обратите внимание сюда!
  public
    procedure run;
end;

procedure TMyDynArrayClass.run;
begin

  SetLength(DynArrayClass, 3);

  DynArrayClass[0]:= TMyClass.Create;
  DynArrayClass[1]:= TMyClass.Create;
  DynArrayClass[2]:= TMyClass.Create;

  DynArrayClass[0].write_str('000');
  DynArrayClass[1].write_str('111');
  DynArrayClass[2].write_str('222');

  ShowMessage('N0 = ' + DynArrayClass[0].read_str);
  ShowMessage('N1 = ' + DynArrayClass[1].read_str);
  ShowMessage('N2 = ' + DynArrayClass[2].read_str);

end;


Код: Выделить всё

procedure TForm1.Button1Click(Sender: TObject);
var MyDynArrayClass : TMyDynArrayClass;
begin

  MyDynArrayClass:= TMyDynArrayClass.Create;

  MyDynArrayClass.run;

end;
CynicRus
постоялец
Сообщения: 106
Зарегистрирован: 28.06.2012 14:31:11

Сообщение CynicRus »

Я бы использовал список для этого, точнее обёртку с generic-списком для этих классов. А уже этот класс-обёртку использовал бы для работы с TMyClass. Типа - TMyClassManager.
Аватара пользователя
Sharfik
энтузиаст
Сообщения: 839
Зарегистрирован: 20.07.2013 01:04:30

Сообщение Sharfik »

Код: Выделить всё


procedure TMyDynArrayClass.run;
begin

  SetLength(DynArrayClass, 3); // Count=3? или от 1...до 1000000? Тормозить будет, если второй вариант. Либо заранее выделять больше, либо TList использовать.

  DynArrayClass[0]:= TMyClass.Create;
  DynArrayClass[1]:= TMyClass.Create;
  DynArrayClass[2]:= TMyClass.Create;
.....
end;
Аватара пользователя
Tango
постоялец
Сообщения: 162
Зарегистрирован: 31.05.2012 17:07:30

Сообщение Tango »

А почему не TList?
Аватара пользователя
fgcsDenis
незнакомец
Сообщения: 2
Зарегистрирован: 06.11.2015 17:12:07

Сообщение fgcsDenis »

А ещё, для решения ряда задач (особенно рекурсивных) вам сможет понадобиться ссылочный список (linked list), Допустим у вашего класса TMyClass есть свойство NextLinked того же типа TMyClass и методы AddLink, DeleteLink. При создании первого экземпляра TMyClass внешним кодом в вашей программе, свойство NextLinked возвращает ссылку на экземпляр из которого оно и вызвано или nil в зависимости от ваших задач. При добавлении экземпляров через метод AddLink в свойство NextLinked записывается ссылка на созданный дочерний экземпляр, а в дочернем экземпляре в том же свойстве записывается ссылка, которая была у экземпляра-родителя. Так список элементов содержит сам себя, не нуждается в объекте-коллекции. Он может быть однонаправленным, может быть двунаправленным. Может быть зацикленным. Может быть многомерным. Обожаю ссылочные списки! :roll:
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

Sharfik писал(а):// Count=3? или от 1...до 1000000? Тормозить будет, если второй вариант. Либо заранее выделять больше, либо TList использовать.

Про: TList TObjectList, TClassList и NextLinked - понятно.
Но почему она будет тормозить, если 1 000 000 - непонятно?
Или точнее почему она не будет тормозить в TList когда 1 000 000 ?
Или ещё точнее в каких конкретно ситуациях?


.
tema
постоялец
Сообщения: 376
Зарегистрирован: 24.03.2011 19:19:27

Сообщение tema »

Код: Выделить всё

begin
......
  ShowMessage('N0 = ' + DynArrayClass[0].read_str);
  ShowMessage('N1 = ' + DynArrayClass[1].read_str);
  ShowMessage('N2 = ' + DynArrayClass[2].read_str);
  DynArrayClass[0].free;
  DynArrayClass[1].free;
  DynArrayClass[2].free;

end;
zub
долгожитель
Сообщения: 2890
Зарегистрирован: 14.11.2005 22:51:26
Контактная информация:

Сообщение zub »

vitaly_l
в случае большого количества однотипных данных стоит посмотреть в сторону от классов, те же рекорды или объекты автоматически дадут выигрыш в производительности из за несколько другого внутреннего устройства
>>Или точнее почему она не будет тормозить в TList когда 1 000 000 ?
Любая линейная структура начинает тормозить при увеличении количества элементов, TList имеет свойство Capacity что позволяет ему перераспределять память пореже чем простому массиву, но это спасает только при заполнении массива. При дальнейшей работе тормозить будут одинаково - например поиск нужного элемента будет одинаково медленным
Аватара пользователя
vitaly_l
долгожитель
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41
Контактная информация:

Сообщение vitaly_l »

zub писал(а):TList имеет свойство Capacity что позволяет ему

Спасибо, круто Capacity - вкусный "орешек", пойду разгрызу...
zub писал(а):например поиск нужного элемента будет одинаково медленным

Спасибо - после этого вопросы исчезли сами собой, но Capacity я всё равно разгрызу...
Всем хорошего настроения!
.
nic1982
новенький
Сообщения: 48
Зарегистрирован: 17.05.2011 16:34:05

Сообщение nic1982 »

Хочу отчитаться о проделанной работе.

Динамический массив с классами оправдал себя в простом случае, описание ниже.
Есть некая территория, эта территория разбита на несколько районов, в каждом районе несколько филиалов.
Необходимо было создавать отчеты по районам, чуть меньше 10 разных типов отчетов.
Некоторые отчеты простые, другие же более сложные.
Простые это те в которых сводная информация по всем филиалам в районе.
Сложные же те в которых информация по каждому филиалу отдельно.
В простых одна страница или несколько страниц если отчет длинный.
В сложных несколько страниц, страница на филиал или несколько страниц если отчет длинный.
Количество филиалов колеблется в зависимости от районов, филиалов максимум несколько десятков, минимум пару штук.
Все классы рождаются и умирают вместе, если бы это было не так то динамический массив с классами не подошел бы.
Почему я выбрал классы а не рекорды ?
Потому что проще, разделить по отчет или филиал-отчет.
Разделение чисто для своего удобства на данные и алгоритмы которые их обрабатывают.
ООП все таки очень удобно, когда имеешь дело с со сложными и большими вещами.
Я люблю рекорды и использую их внутри классов.
Плюсом можно реализовать многопоточность.
Абстракция: на рекордах получились бы бараки,
на классах получились индивидуальные квартиры (у кого многоэтажный дом, у кого просто дом).
В будущем добавятся новые типы отчетов.

Сейчас программа выглядит так (псевдокод):

Код: Выделить всё

Модуль Отчет1
ТОтчет1=класс
  данные
  методы

Модуль Отчет2_по_филиалу
ТОтчет2_по_филиалу=класс
  данные
  методы

Модуль Отчет2
ТОтчет2=класс
  данные : динамический массив ТОтчет2_по_филиалу // вот и он динамический массив классов
  методы

Модуль Главный
   Отчет1 : ТОтчет1
   Отчет2 : ТОтчет2

   Отчет1:=ТОтчет1.Создать
   Отчет2:=ТОтчет2.Создать

   Отчет1.СобратьДанные
   Отчет2.СобратьДанные   
   
   Отчет1.СохранитьПоказатьРаспечататьОтчет 
   Отчет2.СохранитьПоказатьРаспечататьОтчет
   
   Отчет1.Удалить
   Отчет2.Удалить
Ответить