Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Компоненты";
Текущий архив: 2006.06.04;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.46 MB
Время: 0.045 c
4-1142155221
Handle
2006-03-12 12:20
2006.06.04
Снова процессы


3-1144221294
RomanH
2006-04-05 11:14
2006.06.04
Репликация данных


4-1141653957
GrayFace
2006-03-06 17:05
2006.06.04
Получение содержимого регистров при исключении


15-1147046790
Точка Ру
2006-05-08 04:06
2006.06.04
Есть ли функция удаления всех комментариев?


1-1146061673
Unnamed Player
2006-04-26 18:27
2006.06.04
ScrollBy





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский