При описании нового класса важен разумный компромисс. С одной стороны, требуется скрыть от других методы и поля, представляющие собой внутреннее устройство класса (для этого и придуманы свойства). Маловажные детали на уровне пользователя объекта будут бесполезны и только помешают целостности восприятия.
С другой стороны, если слишком ограничить того, кто будет порождать классы-потомки, и не обеспечить ему достаточный набор инструментальных средств и свободу маневра, то он и не станет использовать ваш класс.
В модели объектов языка Object Pascal существует механизм доступа к составным частям объекта, определяющий области, где ими можно пользоваться (области видимости).
Поля и методы могут относиться к четырем
группам (секциям), отличающимся областями видимости. Методы и свойства могут быть общими
(секция public), личными (секция
private), защищенными (секция
Области видимости, определяемые первыми тремя директивами, таковы.
Рассмотрим пример, иллюстрирующий три варианта областей видимости.
Листинг 1.1. Пример задания областей видимости методов
unit First; | unit Second;
interface | interface
| uses First;
type | type
TFirstObj = class | TSecondObj =class(TFirstObj}
private | procedure Method4;
procedure Methodl; | end;
protected |
procedure Method2; |
public |
procedure Methods; |
end; |
procedure TestProcl; | procedure TestProc2;
implementation | implementation
uses dialogs; | varAFirstObj :TFirstObj;
var AFirstObj: TFirstObj;|ASecondObj: TSecondObj;
procedure TestProcl; | procedure TSecondObj.Method4;
begin | begin
AFirstCbj := TFirstObj.Create; | Methodl; {недопустимо -
AFirstObj.Methodl;(допустимо)|
|произойдет ошибка компиляции}
AFirstObj.Method2; {допустимо}| Method2; {допустимо}
AFirstObj.MethodS; {допустимо}| Methods,- {допустимо}
AFirstObj.Free; | end;
end;
| procedure TestProc2;
procedure TFirstObj.Methodl; | begin
begin |AFirstObj:=TFirstObj.Create;
ShowMessage('1'); |AFirstObj.Methodl;{недопустимо}
end; |AFirstObj.Method2;{недопустимо}
procedure TFirstObj.Method2;
|AFirstObj.Method3;{допустимо}
begin |AFirstObj.Free;
ShowMessage('2');
Methodl; |ASecondCbj:= TSecondObj.Create;
end; |ASecondObj.Methodl;{недопустимо}
procedureTFirstObj.Method3;
|ASecondObj.Method2;{допустимо}
begin |ASecondObj.MethodS;{допустимо}
ShowMessage('3'); |ASecondObj.Free;
Method2; | end;
end; |end.
end. |
Если к этому примеру добавить модуль Third и попробовать вызвать методы классов TFirstObj и TSecondObj оттуда, то к числу недоступных будет отнесен и Method2 — он доступен только в том модуле, в котором описан.
Наконец, область видимости, определяемая четвертой директивой — published, имеет особое значение для интерфейса визуального проектирования Delphi. В этой секции должны быть собраны те свойства объекта, которые будут видны не только во время исполнения приложения, но и из среды разработки. Публиковать можно свойства большинства типов, за исключением старого типа real (теперь он называется rеаl48), свойств типа "массив" и некоторых других. Все свойства компонентов, доступные через
Инспектор объектов, являются их опубликованными свойствами. Во время выполнения такие свойства общедоступны, как и public.
Три области видимости — private, protected, public — как бы упорядочены по возрастанию видимости методов. В классах-потомках можно повысить видимость методов и свойств, но не понизить ее. При описании дочернего класса можно переносить методы и свойства из одной сферы видимости в другую, не переписывая их заново и даже не описывая — достаточно упомянуть о нем в другом месте:
type
TFirstObj = class
private
FNumber: Integer;
protected
property Number: Integer read: FNumber;
end;
...
TSecondObj = class(TFirstObj)
published
property Number;
end;
Если какое-либо свойство объекта из состава VCL принадлежит к области public, вернуть его в private невозможно. Напротив, обратная процедура широко практикуется в Delphi. У многих компонентов (например, TEdit) есть предок (в данном случае TCustomEdit), который отличается только отсутствием опубликованных свойств. Так что, если вы хотите создать новый редактирующий компонент, порождайте его на базе TCustomEdit и публикуйте только те свойства, которые считаете нужными. Разумеется, если вы поместили свойство в область private, "достать" его оттуда в потомках возможности уже нет.