Читаем О чём не пишут в книгах по Delphi полностью

В этом классе два свойства Prop1 и Prop2, значение одного из которых определяется полем FProp1, а другого — функцией GetProp2. Оба свойства предназначены только для чтения, но для того эффекта, о котором здесь пойдет речь, это не принципиально: свойства, значения которых можно менять, ведут себя в этом отношении точно так же.

Пусть X — это переменная типа TSomeClass. Легко убедиться, что компилятор допускает получение адреса свойства Prop1, т. е. конструкция вида @X.Prop1 считается допустимой. Результатом выполнении этого оператора станет указатель на поле FProp1. А вот конструкцию @X.Prop2 компилятор не допускает, выдаёт ошибку Variable required.

Ошибкой компилятора здесь является то, что он допускает получение адреса в первом случае, т. е. для свойства, значение которой берется из переменной. Это грубейшее нарушение принципа инкапсуляции, лежащего в основе объектно-ориентированного программирования, причем сразу по двум причинам. Во-первых, пользователь класса не должен видеть его внутреннюю реализацию, а здесь пользователь может определить, как читается свойство, по возможности применения оператора @ к нему. Во-вторых, пользователь класса должен взаимодействовать с ним строго через предоставленный интерфейс, а у нас получается, что, узнав адрес поля FProp1, пользователь сможет менять его значение в обход предусмотренных для этого в классе механизмов.

К счастью, ситуации, в которых эта недоработка компилятора могла бы принести пользу, крайне редки. Но если вы все-таки столкнулись с такой ситуацией, настоятельно рекомендуем не поддаваться соблазну и искать другие способы решения проблемы. Если класс, к полю которого вы хотите получить доступ таким образом, написан вами, то это веский повод пересмотреть внешний интерфейс класса, т. к. при его проектировании скорее всего, были допущены серьезные ошибки. Если это «чужой» класс, подумайте о том, что в следующей версии этого класса автор может изменить реализация свойства, и тогда ваш код откажется компилироваться.

<p>3.4.10. Невозможность использования некоторых свойств оконного компонента в деструкторе</p>

Проблема, о которой пойдет речь в этом разделе, гораздо шире, чем это явствует из заголовка. Однако наиболее ярко она проявится именно в этом случае. Поэтому мы начнем именно с этой ситуации, а потом рассмотрим проблему более широко.

Проблему демонстрирует пример ParentWnd на компакт-диске. В нем создан компонент TWrongCombo, наследник TComboBox. Листинг 5.67 содержит код компонента.

Листинг 3.63. Компонент TWrongCombo

type

 TWrongCombo = class(TComboBox)

 public

destructor Destroy; override;

 procedure AddItem(const Title: string);

 end;

destructor TWrongCombo.Destroy;

var

 I: Integer;

begin

 for I:= 0 to Items.Count — 1 do

if Assigned(Items.Objects[I]) then

 Dispose(PDateTime(Items.Objects(I]));

 inherited;

end;

procedure TWrongCombo.AddItem(const Title: string);

var

 P: PDateTime;

begin

 New(P);

 P^:= Now;

 Items.AddObject(Title, TObject(P));

end;

Класс TWrongCombo с каждым элементом, добавленным с помощью метода AddItem, связывает значение типа TDateTime, хранящее время добавления элемента. В разд. 3.4.6 мы уже познакомились с возможностью связывания данных с элементом списка с помощью свойства Items.Objects. Но так мы можем связать с элементом только 4-байтное значение, а тип TDateTime занимает 8 байтов. Поэтому значение TDateTime мы будем хранить в динамической памяти, а с элементом свяжем указатель на него.

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

Теперь попробуем воспользоваться компонентом. На главной форме программы ParentWnd находится кнопка Wrong Combo, при нажатии на которую создается компонент типа TWrongCombo (листинг 3.64).

Листинг 3.64. Реакция на кнопку Wrong Combo

procedure TForm1.BtnWrongComboClick(Sender: TObject);

begin

 if FWrongCombo = nil then

 begin

FWrongCombo:= TWrongCombo.Create(Self);

 FWrongCombo.Left:= 10;

 FWrongCombo.Top:= 10;

 FWrongCombo.Parent:= Self;

FWrongCombo.AddItem('One');

 FWrongCombo.AddItem('Two');

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных