Раздел published оказался необходимым при введении в Object Pascal возможности установки свойств и поведения компонент еще на этапе конструирования форм и самого приложения (design-time) в среде визуальной разработки программ Delphi. Именно published-объявления доступны через Object Inspector, будь это ссылки на свойства или обработчики событий. Во время исполнения приложения раздел объекта published полностью аналогичен public.
Следует отметить тот факт, что при порождении нового класса путем наследования возможен перенос объявлений из одного раздела в другой с единственным ограничением: если вы производите скрытие объявления за счет его переноса в раздел private, в дальнейшем его "вытаскивание" у наследника в более доступный раздел в другом модуле будет уже невозможен. Такое ограничение, к счастью, не распространяется на динамические методы-обработчики сообщений Windows.
Пример описания класса с заданными областями видимости приведен ниже.
4. ИНКАПСУЛЯЦИЯ
Классическое правило объектно-ориентированного программирования утверждает, что для обеспечения надежности нежелателен прямой доступ из других объектов к полям объекта: чтение и обновление их содержимого должно производиться посредством вызова соответствующих методов. Это правило и называется инкапсуляцией. До сих пор идея инкапсуляции внедрялась в программирование только посредством призывов и примеров в документации, но в языке же Object Pascal появилась соответствующая конструкция. В объектах Object Pascal пользователь объекта может быть полностью отгорожен от его полей при помощи свойств.
Работу со свойствами рассмотрим на следующем примере. Пусть мы создали при помощи дизайнера форм Delphi экранную форму Forml с двумя элементами визуальных компонент: Button 1 и Label 1 (рис. 1).
Рис. 1. Экранная форма примера
Кликнем кнопку Button1 и отредактируем исходный текст модуля до следующего текста:
unit testir;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type
TSomeType = String;
type
TAnObject = class(TObject)
private
FValue: TSomeType;
function GetAProperty: TSomeType;
procedure SetAProperty (ANewValue: TSomeType);
public
property AProperty: TSomeType
read GetAProperty
write SetAProperty;
end;
var
Form1: TForm1;
AnObject: TAnObject;
implementation
{$R *.DFM}
procedure TForm1.ButtonlClick(Sender: TObject);
begin
AnObject:= TAnObject.Create;
AnObject.AProperty:= 'Привет!';
Label1.Caption:= AnObject.AProperty;
end;
procedure TAnObject.SetAProperty(
ANewValue: TSomeType);
begin
FValue:= ANewValue; {Засылка значения в поле}
end;
function TAnObject.GetAProperty: TSomeType;
begin
GetAProperty:= FValue; {Чтение значения из поля}
end;
end.
Сохраним проект (Save Project As). При сохранении проекта укажем новое имя модуля — testir и новое имя проекта — PrTestir. Рассмотрим текст получившегося файла проекта (пункты меню View и далее Project Source):
program PrTestir;
uses
Forms,
testir in 'testir.pas' {Form1};
{$R *.RES}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Данный файл содержит текст основной программы PrTestir. К основной программе подключаются модуль Forms (для работы с формой) и исходный код модуля testir. Три исполняемых оператора основной программы последовательно организуют новый вычислительный процесс выполнения написанной программы PrTestir, создадут объект формы Form1, осуществят запуск программы на выполнение (Run).
В набранном примере текст модуля содержит сгенерированный текст объявления объектного типа Tform1. В типе содержатся указания на агрегацию в данном классе объекта кнопки Button1: Tbutton и объекта Label1: Tlabel. Благодаря агрегации экземпляры объектов кнопки и надписи будут создаваться одновременно с созданием экземпляра объекта формы, в результате чего как бы получится совместно работающий с кнопкой и надписью объект формы. В типе Tform1 Delphi по двойному щелчку мыши по кнопке <Button1> сгенерировала прототип вызова метода:
procedure Button1Click(Sender: TObject).
Также Delphi автоматически сгенерировала переменную объектного типа
var
Form1: TForm1;
и в секции реализации вставила текст "пустой" процедуры Button1Click отработки действий по нажатию кнопки Button1.
Рассмотрим элементы, добавленные нами в текст модуля по реализации инкапсуляции. Итак, нами был набран текст описания класса TAnObject и переменная данного объектного типа AnObject:
type
TAnObject = class(TObject) private
FValue: TSomeType;
function GetAProperty: TSomeType;
procedure SetAProperty (ANewValue: TSomeType);
public
property AProperty: TSomeType
read GetAProperty
write SetAProperty;
end;
var
AnObject: TanObject.
Обычно свойство (property) определяется тремя своими элементами: полем и двумя методами, которые осуществляют его запись/чтение:
private
FValue: TSomeType;
function GetAProperty: TSomeType;
procedure SetAProperty (ANewValue: TSomeType);
public
property AProperty: TSomeType
read GetAProperty