Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lektsii_po_OOP док.doc
Скачиваний:
13
Добавлен:
28.03.2015
Размер:
313.34 Кб
Скачать

Инкапсуляция при помощи свойств(новое в дельфи)

Свойство - это имя скрывающее реализацию доступа к информации класса. Благодаря использованию свойств можно существенно модифицировать внутреннее строение класса не внося при этом каких либо изменений в код, использующий этот класс. Синонимом слова свойство является виртуальное поле.

С точки зрения пользователя класса свойство этого класса выглядит как поле – его значение можно считывать и записывать. Например,

Edit1.Text:=Button1.Caption;

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

1) Можно напрямую отобразить свойство на внутренние поля класса.

2) Можно назначить методы, которые должны использоваться для осуществления, чтения, и записи значений свойства. Если свойства отражены на методы, то в рамках этих методов может выполняться целый комплекс действий, связанных с доступом к значению свойства.

Например:

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

Технически свойства – это идентификатор, который отображается на данные или методы при помощи специальных ключевых слов read и write , например.

Введем в класс Tdate свойство Month/

Есть специальное ключевое свойство PROPERTY

Property month:integer read Fmonth

Write SetMonth

Для чтения используется частное поле Fmonth, а для изменения его значения метод SetMonth. Этот метод должен быть определен внутри класса. Влзможна любая другая комбинация.

Например, метод можно использовать и для чтения и для записи.

Или наоборот читать при помощи метода а записывать при помощи поля.

Property Month: integer read GetMonth write SetMonth;

Property Month:integer read GetMonth write FMonth;

Использование метода для модификации значений свойства является общепринятой практикой.

Обычно связанные со свойством данные и методы являются частными PRIVATE или защищенными PROTECTED, а само свойство является общедоступным.(обычная практика ООП). Т..е. любой доступ к этим данным и методам осуществляется только с использованием свойств.

Инкапсуляция при помощи свойств является как упрощенной, так и расширенной.

+ Расширенной она является потому, что можно менять не только внутренне представление данных и функций доступа, но и добавлять новые функции доступа, не меняя при этом кода, который обращается к классу.

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

Механизм завершения класса (ctrl shift C) может автоматически сформировать заготовки методов доступа к внутренним данным класса для любого из определенных свойств.

TMyClass

{ctrl shift C} /////// он добавит защищ.поле сам в определение класса

Property x:integer

End;

……………………

Implementation SetX;

…………………….

Procedure TMyclass

Begin

Fx:=Value;

End;

TMyclass

Private

FX:integer;

Procedure SetX(const value:integer);

Public

Property x:integer read FX write SetX;

End;

Примеры использования свойств:

1) класс TDate.

Type TDate = class

Private

fDate : TDateTime;

procedure SetDay(const Value:integer);

procedure SetMonth(const Value:ineteger);

procedure SetYear(const Value:integer);

function GetDay:integer;

function GetMonth: integer;

function GetYear:integer;

public

procedure SetValue( m,d,y : ineteger ); overload;

procedure SetValue(NewDate:TdateTime); overload;

function heapYear:Boolean;

function GetTex : string;

procedure Increase;

//////добавляем свойства(всё проектируем на методы.)

property Day:integer read GetDay write SetDay;

property Month:integer read GetMonth write SetMonth;

property Year:integer read GetYear write SetYear;

end;

Пример реализации методов Set Get

Function TdateGetMonth;

Begin

Result:=MonthOf(FDate); ///в модуле DateUtils.

End;

Procedure TDateSetMonth(const value:integer);

Begin

fDate:=recodeMonth(fDate,Value);

End;

*В процессе работы приложение должно создать объект класса TDate (обычно на методе OnCreate формы). В приложении он может выглядит например: поля редактирования для дня, месяца и года, из них можно читать значение и записывать их в свойства, а можно читать из свойств и записывать в эти поля. + на форме надо расположить кнопки, соответствующие методам класса(Increase…..). Т.е. надо полностью протестировать класс.

Пример обращения к свойству:

EdDay.Text:=IntToStr(ADay.Day);///происх обр к методу Get. Get выбир тек день…и т.п.

Aday.Year:=StrToInt(EdYear.Text);

При объявлении свойства директиву write можно не использовать. И тогда свойство будет предназначено только для чтения (read only). Точно так же и с директивой read(будет write only).

Пример 2:

1 из задач инкапсуляции – сокращение числа глобальных переменных, используемых программой.

Если мы меняем представление поля класса, то изменения зактрагивают код нескольких методов этого класса.

Т.е. сокрытие информации позволяет инкапсулировать изменения.

Пример:

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

Var Form1:TForm1;

NClicks:integer;

Другие формы могут это использовать в своих целях. Данные связаны не с конкретным экземпляром формы, а со всей программой. Т.е. если есть 2 формы, они могут исп.эти данные совместно.

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

Type TForm1=class(TForm)

Public

nClicks:integer;

end;

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

Таким образом данные можно объявить в Private и создать метод для чтения их значения.

Type TForm1=class(TForm)

private

nClicks:integer;

public

function GetClicks:integer;

end;

*Лучшим решением будет добавление свойства в форму.

Для этого

Type TForm1=class(TForm)

public

property NClick:integer;

end;

( и ctrl shift C)

Необходимо добавить обработку события OnClick для формы в рамках которого будет происходить увеличение значения свойства и отображение его значений в заголовке формы.

Procedure TForm1.FormClick(sender:object)

Begin

Inc(Nclicks);

Caption:=’Clicks’+IntToStr(Nclicks);

End;

Как создать еще одну формы такого же типа????

Procedure TForm1.btnCreateFormClick(sender:Tobject);

Begin

With TForm1.Create(Self) do

Show;

End;

3) Применение свойств для инкапсуляции доступа к компонентам формы.

Пример:

Имеется главная форма со строкой состояния в которой отображается информация, которая например может поступать из вспомогательных форм.

Main

Form1.StatusBar1.SimpleText:=’!!!’;

Если в дальнейшем возникнет потребность поменять интерфейс …..

Property Statustext:string

Read GetTExt write SetText;

…………………

Function TForm1.GetText;string;

Begin

Result:=StatusBar1.SimpleText;

End;

Procedure TFrom1.SetTex(const Value:integer)

Begin

StatusBar1.SimpleText:=Value;

End;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]