Планирование уроков на учебный год (по учебнику К.Ю. Полякова, Е.А. Еремина, полный углублённый курс, по 4 часа в неделю)



Урок 91
Скрытие внутреннего устройства
(§49. Скрытие внутреннего устройства)




Содержание урока

Инкапсуляция

Свойство

Вопросы и задания

Задача


Свойство


Свойство — это способ доступа к внутреннему состоянию объекта, имитирующий обращение к его внутренней переменной.

Свойство color в нашем случае можно определить так:

type ТРеn - class 
	private
		FColor: string; 
		function getColor: string; 
		procedure setColor(newColor: string); 
	public
		property color: string read getColor
						write setColor;
end;

Здесь методы getColor и setColor перенесены в раздел private, т. е. закрыты от других объектов. Однако есть общедоступное свойство color строкового типа:

property color: string read getColor
		write setColor;

При чтении этого свойства (англ. read) вызывается метод getColor, а при записи нового значения (англ. write) — метод setColor. В программе можно использовать это свойство так:

pen.color:='FFFF001;	{изменение цвета}
writeln( 'цвет пера:	pen.Color );
					{получение цвета}

Поскольку приведённая выше функция getColor просто возвращает значение поля FColor и не выполняет никаких дополнительных действий, можно было вообще удалить метод getColor и объявить свойство так:

property color: string read FColor write setColor;

В этом случае при чтении выполняется прямой доступ к полю.

Таким образом, с помощью свойства color другие объекты могут изменять и читать цвет объектов класса ТРеn. Для обмена данными с «внешним миром» важно лишь то, что свойство color — символьного типа, и оно содержит 6-символьный код цвета. При этом внутреннее устройство объектов ТРеn может быть любым, и его можно менять как угодно. Покажем это на примере.

Хранение цвета в виде символьной строки неэкономно и неудобно, так как большинство стандартных функций используют числовые коды цвета. Поэтому лучше хранить код цвета как целое число, и поле FColor сделать целого типа:

FColor: integer;

При этом необходимо поменять методы getColor и setColor, которые непосредственно работают с этим полем:

function TPen.getColor: string;
begin
	Result:=IntToHex(FColor,6);
end;
procedure TPen.setColor(newColor: string);
begin
	if Length(newColor)<>6 then
		FColor:=0 {если ошибка, то чёрный цвет} 
	else begin
		FColor:=StrToInt(1 $'+newColor); 
	end;
end;

Для перевода числового кода в символьную запись используется функция IntToHex, входящая в библиотеку FreePascal (модуль SysUtils). Её второй параметр — количество цифр, которое будет в шестнадцатеричном числе. Обратный перевод выполняет функция StrToInt. Для того чтобы указать, что число записано в шестнадцатеричной системе, перед ним добавляют символ $.

В этом примере мы принципиально изменили внутреннее устройство объекта: заменили строковое поле на целочисленное. Однако другие объекты даже не «догадаются» о такой замене, потому что сохранился интерфейс — свойство color по-прежнему имеет строковый тип. Таким образом, инкапсуляция позволяет как угодно изменять внутреннее устройство объектов, не затрагивая интерфейс. При этом все остальные объекты изменять не требуется.

Иногда не нужно разрешать другим объектам менять свойство, т. е. требуется сделать свойство «только для чтения» (англ. read-only). Пусть, например, мы строим программную модель автомобиля. Как правило, другие объекты не могут непосредственно менять его скорость, однако могут получить информацию о ней — «прочитать» значение скорости. При описании такого свойства слово write и название метода записи не указывают вообще:

 
type TCar = class 
	private 
		Fv: real;
		...
	public
		property v: real read Fv; 
		...		
end;

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

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

Рис. 7.8

Рис. 7.8



Следующая страница Вопросы и задания



Cкачать материалы урока






Наверх