Для контроля доступа к полям, методам и свойствам классов используются области видимости. В Delphi есть следующие области видимости:
- public
- published
- strict private
- private
- strict protected
- protected
Рассмотрим их на примерах.
public
Элементы секции public не имеют ограничений доступа. Они доступны отовсюду: из методов своего класса, из методов других классов, из своего модуля и из других модулей.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
unit uCircle; interface type TCircle = class public FRadius: Integer; function Area: Extended; end; implementation { TCircle } function TCircle.Area: Extended; begin Result := FRadius * FRadius * Pi; // Поле доступно внутри класса end; end. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
unit uCheckCircle; interface procedure CheckCircle; implementation uses System.SysUtils, Vcl.Dialogs, uCircle; procedure CheckCircle; var Circle: TCircle; begin Circle := TCircle.Create; try Circle.FRadius := 2; // Поле доступно снаружи ShowMessage(FloatToStr(Circle.FRadius)); finally FreeAndNil(Circle); end; end; end. |
1 2 3 4 5 6 7 |
uses uCheckCircle; procedure TForm1.Button1Click(Sender: TObject); begin CheckCircle; end; |
published
Видимость элементов в секции published полностью аналогична секции public. В этом посте рассматривается только поведение касающееся видимости, подробнее в различиях связанных с RTTI описано в документации.
Область по умолчанию
Если не указывать область видимости то она будет аналогичной области public.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
unit uCircle; interface type TCircle = class FRadius: Integer; function Area: Extended; end; implementation { TCircle } function TCircle.Area: Extended; begin Result := FRadius * FRadius * Pi; // Поле доступно внутри класса end; end. |
Аналогично поле видно и из других модулей.
strict private
Самая ограниченная область видимости. Элементы в секции private доступны только из методов класса. К ним нет доступа из методов других объектов, независимо от модуля в котором они находятся. Также к ним нет доступа из наследников данного объекта.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
unit uCircle; interface type TCircle = class strict private FRadius: Integer; public function Area: Extended; end; procedure CheckCircle; implementation uses System.SysUtils, Vcl.Dialogs; { TCircle } function TCircle.Area: Extended; begin Result := FRadius * FRadius * Pi; // Поле доступно внутри класса end; procedure CheckCircle; var Circle: TCircle; begin Circle := TCircle.Create; try Circle.FRadius := 2; // ошибка компиляции ShowMessage(FloatToStr(Circle.FRadius)); finally FreeAndNil(Circle); end; end; end. |
private
Секция private совпадает с секцией strict private, за исключением того что все элементы этой секции доступны из любого метода любого класса в том же модуле в котором объявлен класс.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
unit uCircle; interface type TCircle = class private FRadius: Integer; public function Area: Extended; end; procedure CheckCircle; implementation uses System.SysUtils, Vcl.Dialogs; { TCircle } function TCircle.Area: Extended; begin Result := FRadius * FRadius * Pi; // Поле доступно внутри класса end; procedure CheckCircle; var Circle: TCircle; begin Circle := TCircle.Create; try Circle.FRadius := 2; // работает ShowMessage(FloatToStr(Circle.FRadius)); finally FreeAndNil(Circle); end; end; end. |
Если перенести процедуру CheckCircle
в другой модуль то произойдёт ошибка компиляции, так как FRadius
уже будет недоступен.
strict protected
Элементы объявленные с секции strict protected доступны только из методов самого класса и из классов потомков. От модуля в котором они находятся это не зависит.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
unit uCircle; interface type TCircle = class strict protected FRadius: Integer; public function Area: Extended; end; TSuperCircle = class(TCircle) public function Diameter: Extended; end; procedure CheckCircle; implementation uses System.SysUtils, Vcl.Dialogs; { TCircle } function TCircle.Area: Extended; begin Result := FRadius * FRadius * Pi; // Поле доступно внутри класса end; { TSuperCircle } function TSuperCircle.Diameter: Extended; begin Result := FRadius * 2; // Поле доступно в потомке end; procedure CheckCircle; var Circle: TCircle; begin Circle := TCircle.Create; try Circle.FRadius := 2; // но вне класса также недоступно ShowMessage(FloatToStr(Circle.FRadius)); finally FreeAndNil(Circle); end; end; end. |
protected
Секция protected совпадает с секцией strict protected, за исключением того что все элементы этой секции доступны из любого метода в том же модуле в котором объявлен класс. Ситуация аналогичная private и strict private.