Инкапсуляция и свойства объекта



Под инкапсуляцией понимается скрытие полей объекта с целью обеспечения доступа к ним только посредством методов класса.

В Object Pascal ограничение доступа к полям объекта реализуется с помощью свойств объекта. Свойство объекта характеризуется полем, хранящим значение свойства, и двумя методами, обеспечивающими доступ к полю свойства. Метод установки значения свойства называется методом записи свойства (write), метод получения значения свойства называется методом чтения свойства (read).

В описании класса перед именем свойства записывают ключевое слово property (свойство). После имени свойства указываются его тип, затем имена методов, обеспечивающих доступ к значению свойства. После слова read указывается имя метода, обеспечивающего чтение свойства, после слова write —имя метода, обеспечивающего запись свойства. Ниже приведен пример описания класса TTPerson, содержащего два свойства: Name и Address.

Type

TName=string[15];

TAddress=string[35];

TTPerson = class

Private

   FName:Tname; //значение свойства Name

   FAddress:TAddress; // значение свойства Address

    Constructor Create(Name:Tname);

    ProcedureShow;

    Function GetName:TName;

    Function GetAddress:TAddress;

    Procedure SetAddress(NewAddress:TAddress);

 

Public

Property Name: Tname

read GetName;

Property Address: TAddress

read GetAddress;

write SetAddress;

end;

В программе для установки значения свойства необязательно записывать оператор применения к объекту метода установки значения свойства, можно записать обычный оператор присваивания значения свойству. Например, чтобы присвоить значение свойству Address объекта student, достаточно записать

student.Address:=’С.Петербург, ул. Садовая, 21, кв.3’;

Компилятор перетранслирует приведенный оператор присваивания значения свойству в оператор вызова метода:

student.SetAddress('С.Петербург, ул. Садовая, 21, кв.3');

Внешне использование свойств в программе ничем не отличается от ис­пользования полей объекта. Вместе с тем между свойством и полем объекта существует принципиальное отличие: при присвоении и чтении значения свойства автоматически вызывается процедура, которая выполняет некоторую работу.

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

Оформление данных объекта как свойства позволяет ограничить доступ к полям, хранящим значения свойств объекта, например можно разрешить только чтение. Чтобы операторы программы не могли изменить значение свойства, в описании свойства надо указать только имя метода чтения. Попытка присвоить значение свойству, предназначенному только для чтения, вызывает ошибку времени компиляции В приведенном выше описании класса TTPerson свойство Name доступно только для чтения, а свойство Address — для чтения и записи.

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

//конструктор объекта TTPerson

Constructor TTPerson.Create(Name:TName);

Begin

     Fname:=Name;

end;

//метод получения значения свойства Name

Function TTPerson.GetName;

Begin

      Result:=FName;

end;

//метод получения значения свойства Address

Function TTPerson.GetAddress;

Begin

Result:=FAddress;

end;

//метод изменения значения свойства Address

Procedure TTPerson.SetAddress(NewAddress:TAddress);

Begin

if FAddress =’’

        then FAddress:=NewAddress;

end;

Приведенный конструктор объекта TTPerson создает объект и устанавливает значение поля FName, определяющего значение свойства Name.

Операторы программы, обеспечивающие создание объекта класса TTPerson и установку его свойства, могут быть, например, такими:

student:=TTPerson.create('Иванов');

student.address:=’ул. Садовая, д.21, кв. 3’;

Наследование

Концепция объектно-ориентированного программирования предполагает возможность определять новые классы посредством добавления полей, свойств и методов к уже существующим классам. Такой механизм получения новых классов называется порождением. При этом новый, порожденный, класс (класс-потомок) наследует свойства и методы своего базового, родительского класса.

В объявлении класса-потомка указывается класс родителя. Например, класс TEmployee (сотрудник) может быть порожден от рассмотренного выше класса TTPerson путем добавления поля Department (отдел). Объявление класса TEmployee в этом случае может выглядеть так:

TEmployee = class(TTPerson)

FDepartment:integer; // номер отдела

constructor Create(Name:TName;Dep:integer);

end;

Заключенное в скобки имя класса TTPerson показывает, что класс TEmployee является производным от класса TTPerson. В свою очередь, класс TTPerson является базовым для класса TEmployee.

Класс TEmployee имеет свой собственный конструктор, который обеспечивает инициализацию класса родителя и своих полей. Пример реализации конструктора класса TEmployee:

constructor TEmployee.Create(Name:Tname;Dep:integer);

Begin

inherited Create(Name);

FDepartment:=Dep;

end;

В приведенном примере директивой inherited вызывается конструктор родительского класса, затем присваивается значение полю класса потомка.

После создания объекта производного класса в программе можно использо-. вать поля и методы родительского класса. Ниже приведен фрагмент программы, демонстрирующей эту возможность:

engineer:=TEmployee.create('Сидоров',413);

engineer.address:='ул.Блохина, д.8, кв.10';

Первый оператор создает объект типа TEmployee. Второй устанавливает значение свойства, которое относится к родительскому классу.

Области видимости в классах

Как отмечалось в п. 2.1, помимо объявлений элементов класса (полей, методов, свойств) описание класса, как правило, содержит несколько директив, которые устанавливают степень видимости элементов класса в программе.

Рассмотрим семантику директив видимости.

1. Директива private.

Поля, свойства и методы, описанные в разделе private,называются личными или закрытыми. Сюда помещаются элементы (чаще всего поля), которые выполняют в объекте специфичные функции и которые поэтому целесообразно скрыть от других частей программы, либо такие элементы, для которых по ряду причин не следует разрешать доступ извне объекта.

2. Директива public.

Элементы, описанные в разделе public, называются общедоступными. Они могут быть использованы всюду в программе. Поля, свойства и методы, расположенные сразу после заголовка класса, при выключенной директиве компилятора {$M-}, по умолчанию принимаются общедоступными.

3. Директива protected.

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

4. Директива published.

Поля, свойства и методы, описанные в разделе published, называются опубликованными. Их область видимости эквивалентна области видимости общедоступных описаний. Отличие состоит в том, что информация о них, за исключением ряда типов, например real, на этапе проектирования программы помещается в инспектор объектов. Описания, расположенные сразу после заголовка класса, при включенной директиве компилятора {$M+}, по умолчанию принимаются опубликованными.

5. Директива automated.

Элементы класса, объявленные в разделе automated, называются автоматическими. Их область видимости эквивалентна области видимости общедоступных описаний. Отличие состоит в том, что для автоматических свойств и методов генерируется дополнительная информация, которая используется для реализации OLE-механизма. Использовать директиву automatedимеет смысл при объявлении потомков стандартного класса TAutoObject.

Ниже приведено описание класса TTPerson, в которое включены директивы видимости.

ТТРегsоп = class

Private

FName:TName; { значение свойства Name }

FAddress:TAddress; ( значение свойства Address}

Protected

Constructor Create(Name:TName);

Function GetName:TName;

Function GetAddress:TAddress;

Procedure SetAddress (NewAddress: TAddress);

Property Name:TName

        read GetName;

Property Address:TAddress

         read GetAddress

       write SetAddress;

end;

Примечание.

Если необходимо, чтобы элементы класса были скрыты полностью, определение класса следует поместить в отдельный модуль.


Дата добавления: 2018-04-15; просмотров: 391; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!