Статические структуры: классы
Унифицированный доступ
На первый взгляд один из аспектов приведенной выше классификации может вызывать беспокойство. Во многих случаях необходимо иметь возможность работать с объектом, например с точкой p1, не заботясь о том, какое внутреннее представление используется для p1 - декартово, полярное или иное. Необходимо ли для этого отличать атрибуты от функций?
Ответ зависит от того, с какой точки зрения рассматривать данную проблему - разработчика, автора данного класса POINT или клиента, создавшего класс, использующий POINT. Для разработчика разница между атрибутами и функциями принципиально важна и имеет смысл. Ему необходимо принимать решения о том, какие компоненты будут реализованы как данные в памяти и какие будут доступны в результате вычислений. Но заставлять клиента осознавать эту разницу, было бы серьезной ошибкой. Клиент должен обращаться к значениям x или для точки p1, не заботясь и не имея информации о том, как реализованы соответствующие запросы.
Решение проблемы дает принцип унифицированного доступа (Uniform Access principle), введенный в дискуссии о модульности ( "Модульность" ). Принцип декларирует, что клиент должен иметь возможность доступа к свойствам объекта, используя одинаковую нотацию, вне зависимости от того, как это свойство реализовано - в памяти или как результат вычислений (в пространстве или во времени, в виде атрибута или подпрограммы). Этому важному принципу необходимо следовать при разработке нотации для обращения к компонентам класса. Так выражение, обозначающее значение компонента x объекта p1 будет всегда записываться в виде:
p1.x
вне зависимости от того, осуществляется ли доступ к полю данных объекта или выполняется подпрограмма.
При использовании такой нотации неопределенность может возникать только для запросов без аргументов, которые могут быть реализованы и как функции и как атрибуты. Команда должна быть процедурой, запрос с аргументами должен быть функцией, так как атрибуты не могут иметь аргументов. |
Принцип унифицированного доступа необходим для гарантирования автономности компонентов ПО. Он защищает право создателя класса свободно экспериментировать с различными способами реализации, не создавая помех клиентам. (СМ. "Использование утверждений для документирования: краткая форма класса", "Проектирование по контракту: построение надежного ПО" )
Принцип унифицированного доступа является источником определенных требований и к подготовке документации. Последовательное применение этого принципа должно гарантировать, например, что в официальной документации не содержится сведений о том, является ли данный запрос без аргументов функцией или атрибутом. Это одно из требований к стандартной методике документирования классов, известной как краткая форма класса.
Класс POINT
Ниже приведена версия исходного текста класса POINT. Фрагменты, начинающиеся с двух тире "--", представляют собой комментарии, продолжающиеся до конца строки. Комментарии содержат пояснения, облегчающие понимание текста, и не влияют на семантику класса.
indexing description: "Точка на плоскости" class POINT feature x, y: REAL -- Абсцисса и ордината rho: REAL is -- Расстояние до начала координат (0, 0) do Result := sqrt (x^2 + y^2) end theta: REAL is -- Полярный угол do -- Предлагается реализовать в качестве упражнения (упр. У7.3) end distance (p: POINT): REAL is -- Расстояние до точки p do Result := sqrt ((x - p.x)^2 + (y- p.y)^2) end translate (a, b: REAL) is -- Перемещение на a по горизонтали, b по вертикали do x := x + a y := y + b end scale (factor: REAL) is -- Изменение расстояния до начала координат в factor раз do x := factor * x y := factor * y end rotate (p: POINT; angle: REAL) is -- Поворот вокруг p на угол angle do -- Предлагается реализовать в качестве упражнения (упр. У7.3) end end
Некоторые аспекты приведенного текста неочевидны и требуют дополнительных разъяснений.
Класс в основном состоит из предложения, перечисляющего различные компоненты, вводимого ключевым словом feature. Кроме того, присутствует предложение indexing дающее общее описание ( description ), полезное для понимания функциональности класса, но никак не влияющее на семантику исполнения. Позднее будут рассмотрены три дополнительных предложения: inherit - для наследования; creation - при необходимости использования специального конструктора; invariant - для объявления инвариантов класса. Будет рассмотрена также возможность включения в класс двух или более предложений feature.