Инкапсуляция
Во время построения объектной модели задачи мы выделили отдельные объекты, которые для обмена данными друг с другом используют интерфейс — внешние свойства и методы. При этом все внутренние данные и детали внутреннего устройства объекта должны быть скрыты от «внешнего мира». Такой подход позволяет:
• обезопасить внутренние данные (поля) объекта от изменений (возможно, разрушительных) со стороны других объектов;
• проверять данные, поступающие от других объектов, на корректность, тем самым повышая надёжность программы;
• переделывать внутреннюю структуру и код объекта любым способом, не меняя его внешние характеристики (интерфейс); при этом никакой переделки других объектов не требуется.
Скрытие внутреннего устройства объектов называют инкапсуляцией («помещение в капсулу»).
Заметим, что в объектно-ориентированном программировании инкапсуляцией также называют объединение данных и методов работы с ними в одном объекте.
Разберём простой пример. Во многих системах программирования есть класс, описывающий свойства «пера», которое используется при рисовании линий в графическом режиме. Назовём этот класс ТРеn, в простейшем варианте он будет содержать только одно поле Color, которое определяет цвет. Будем хранить код цвета в виде символьной строки, в которой записан шестнадцатеричный код составляющих модели RGB. Например, ’FFOOFF’ — это фиолетовый цвет, потому что красная (R) и синяя (В) составляющие равны FF16 = 255, а зелёной составляющей нет вообще. Класс можно объявить так:
type ТРеn = class Color: string; end;
По умолчанию все члены класса (поля и методы) открытые, общедоступные (англ. public). Те элементы, которые нужно скрыть, в описании класса помещают в «частный» раздел (англ. private), например, так:
type ТРеn = class private FColor: string; end;
В этом примере поле FColor закрытое. Имена всех закрытых полей далее будем начинать с буквы «F» (от англ. field — поле). К закрытым полям нельзя обратиться извне (это могут делать только методы самого объекта), поэтому теперь невозможно не только изменить внутренние данные объекта, но и просто узнать их значения. Чтобы решить эту проблему, нужно добавить к классу ещё два метода: один из них будет возвращать текущее значение поля FColor, а второй — присваивать полю новое значение. Эти методы доступа назовем getColor (в переводе с англ. — получить Color) и setColor (в переводе с англ. — установить Color):
type TPen=class private FColor: string; public function getColor: string; procedure setColor(newColor: string); end;
Обратите внимание, что оба метода находятся в секции public (общедоступные).
Что же улучшилось по сравнению с первым вариантом (когда поле было открытым)? Согласно принципам ООП, внутренние поля объекта должны быть доступны только с помощью методов. В этом случае внутреннее представление данных может как угодно отличаться от того, как другие объекты «видят» эти данные.
В простейшем случае метод getColor можно написать так:
function TPen.getColor: string; begin Result:=FColor; end;
В методе setColor мы можем обрабатывать ошибки, не разрешая присваивать полю недопустимые значения. Например, установим, что символьная строка с кодом цвета, передаваемая нашему объекту, должна состоять из шести символов. Если эти условия не выполняются, будем записывать в поле FColor код чёрного цвета ’000000’:
procedure TPen.setColor(newColor: string); begin if Length(newColor)<>6 then FColor:='000000' { если ошибка, то чёрный цвет) else FColor:=newColor end;
Теперь если pen — это объект класса TPen, то для установки и чтения его цвета нужно использовать показанные выше методы:
pen.setColor ('FFFF00') ; {изменение цвета) writeln( 'цвет пера: pen.getColor ); {получение цвета)
Итак, мы скрыли внутренние данные, но одновременно обращение к свойствам стало выглядеть довольно неуклюже: вместо pen. Color : = 'FFFF00' теперь нужно писать pen . setColor ('FFFF00') . Чтобы упростить запись, во многие объектно-ориентированные языки программирования ввели понятие свойства (англ. property), которое внешне выглядит как переменная объекта, но на самом деле при записи и чтении свойства вызываются методы объекта.
Следующая страница Свойство