Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.06.04;
Скачать: CL | DM;

Вниз

Инкапсуляция и взаимодействие   Найти похожие ветки 

 
dvp_Dima   (2005-11-24 21:44) [0]

Здравствуйте мастера.

При практическом решении задачи возник теоретический вопрос:

Имеются 2 класса:


TLittleClass = class
 property FirstProperty: TSomeType;
 property SecondProperty: TAnotherType;
end;

TBigClass = class
private
 FChanged: Boolean;
 FLittleItems: array of TLittleClass;
public
 property Changed: Boolean read FChanged;
 procedure DoChangeSomething;
 ...
end;


Т.е. класс TBigClass инкапсулирует класс TLittleClass.
У объекта типа TBigClass имеется свойство Changed (и соответствующее ему поле FChanged), которое предназначено для хранения факта внесения изменений в этот объект.
На практике это означает, что при вызове DoChangeSomething флаг FChanged устанавливается в True;

Вопрос: Как организовать взаимодействие описанной системы, чтобы при внесении изменений в любой из инкапсулированных объектов FLittleItems: array of TLittleClass флаг FChanged устанавливался в True;

Сам я пока нашёл только два решения, но оба они мне не нравятся:

1. В классе TLittleClass сделать аналогичное поле FChanged и поддерживать его значение средствами самого класса. А при вызове TBigClass.Changed возвращять TBigClass.FChanged or TBigClass.FLittleItems[0..Count].FChanged

2. Создать в лкассе TLittleClass свойство OnChange. При создании объекта TBigClass назначить TLittleClass.OnChange действие, устанавливающее флаг TBigClass.FChanged в True.

Подскажите, как правильно организовать это?


 
dvp_Dima   (2005-11-24 22:04) [1]

Да, забыл сказать - второй вариант не корректен, потому что TLittleClass.OnChange будет Public и следовательно будет доступен в обход TBigClass


 
oleg_   (2005-11-24 23:21) [2]

Я в подобных случая для класса littleclass прописываю ссылку на объект класса bigclass


 
dvp_Dima   (2005-11-25 00:49) [3]

Т.е. по аналогии с Parent в визуальных компонентах?

Но в этом случае придётся FChanged делать открытым на запись, что конечно не критично, но всё-таки как-то не правильно


 
ЮЮ ©   (2005-11-25 03:43) [4]

>Но в этом случае придётся FChanged делать открытым на запись

Зачем? Может лучше
property Changed: Boolean read FChanged write SetChanged

Кстати, будет ли  TBigClass.Changed, если в списке нескольких эземпляров TLittleClass был только один, который  Changed, и он был удален из списка? Тогда может лучше так(если список не очень большой):

property Changed: Boolean read GetChanged;

function GetChanged: boolean;
var
 i: integer;
begin
 Result := false;;
 for i := 0 to High(FLittleItems) do
   if FLittleItems[i].Changed then begin
     Result := true;
     exit;
   end
end;


 
Юрий Зотов ©   (2005-11-25 05:31) [5]

> dvp_Dima   (24.11.05 21:44)

Наследуйте TLittleClass от TCollectionItem, а TBigClass - от TCollection, там все уже реализовано (см. методы Changed). Или сделайте по аналогии с коллекциями.


 
Igorek ©   (2005-11-25 08:57) [6]

> 2. Создать в лкассе TLittleClass свойство OnChange. При
> создании объекта TBigClass назначить TLittleClass.OnChange
> действие, устанавливающее флаг TBigClass.FChanged в True.

Вот так хорошо. Но действие - это метод TBigClass, который динамически назначен обработчиком TLittleClass.OnChange (пусть это будет LittleItemChanged(Sender)). Но есть потенциальный недостаток. Вообще говоря поле свойства, должно меняться только в методе записи св-ва. Можно конечно в LittleItemChanged написать Changed := True (предварительно добавив метод записи). Но проблема возникает, когда происходит много изменений, и TBigClass после каждого должен выполнить какую-то затратную операцию (перерисовку например). Вмешаться в работу метода записи напрямую Вы не можете. Тогда надо реализовать механизм BeginUpdate, EndUpdate, IsUpdating - если TBigClass в процессе изменения, то при вызове SetChange, эта затратная операция не выполняется. А в EndUpdate надо инициировать эту затратную операцию.


 
Юрий Зотов ©   (2005-11-25 15:24) [7]

> Igorek ©   (25.11.05 08:57) [6]

> Тогда надо реализовать механизм BeginUpdate, EndUpdate...

То есть, повторить все то, что уже сделано в классе TCollection. Значит, надо просто от него и отнаследоваться, это будет и проще, и надежнее.


 
dvp_Dima   (2005-11-26 21:53) [8]

Юрий Зотов ©   (25.11.05 05:31) [5]

Спасибо, думаю это будет действительно правильный подход.



Страницы: 1 вся ветка

Текущий архив: 2006.06.04;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.029 c
4-1142384579
GRAVIX
2006-03-15 04:02
2006.06.04
Работа с реестром на чистом WINAPI


2-1147681226
evg123
2006-05-15 12:20
2006.06.04
Печать DBGrid a


15-1146945037
casandra
2006-05-06 23:50
2006.06.04
Что вы празднуете 9 мая?


6-1137435217
guitarist
2006-01-16 21:13
2006.06.04
Hyperterminal


15-1146925008
vrem
2006-05-06 18:16
2006.06.04
Размер шрифта - название веток, ответы - в DMClient