определяет
Такой синтаксис позволяет легко распознавать различные виды компонентов, подчеркивая в то же время их фундаментальные общности. Само понятие компонента, объединяющее подпрограммы и атрибуты лежит в русле принципа унифицированного доступа. Общность в объявлениях атрибутов основана на тех же принципах.
Атрибуты или функции?
Рассмотрим подробнее следствия принципа унифицированного доступа и объединения атрибутов и подпрограмм под общим заголовком - компоненты. (См.'Унифицированный доступ', лекция 3. См. также данную лекцию.)
Принцип декларирует, что клиенты модуля обращаются ко всем его сервисам идентичным образом независимо от способа их реализации. В данном случае в роли сервисов выступают компоненты класса, и для клиентов имеет значение только доступность соответствующих компонентов, независимо от того, как они реализованы атрибутами или функциями.
Рассмотрим класс
Isabelle.age
то единственно важным будет то, что
Нотация для доступа к атрибуту идентична вызову подпрограммы, а нотации для объявления этих видов компонентов одинаковы настолько, насколько это концептуально возможно. Если в дальнейшем автор класса заменит реализацию функции на атрибут или наоборот, то это никак не отразится на клиентах данного класса.
Различие в точках зрения поставщика и клиента на атрибут представлено на рис. 7.4 и рис. 7.5, использованных для определения понятия компонента. Рис. 7.5 иллюстрирует разницу между подпрограммами и атрибутами - это внутреннее представление с позиций реализации, используемое поставщиком. Рис. 7.4 в качестве первичного критерия использует разницу между командами и запросами - это внешнее представление клиента.
Решение рассматривать атрибуты и функции без параметров как эквивалентные для клиентов имеет два важных следствия, рассматриваемые подробно в последующих лекциях:
[x]. Первое следствие касается программной документации. Стандартная документация класса для клиента, известная как краткая форма класса, составляется так, чтобы отсутствовала разница в описаниях атрибутов и функций без параметров. (См. 'Использование утверждений в документации: краткая форма класса', лекция 11)
[x]. Второе следствие связано с наследованием, как основным способом адаптации программных элементов к новым условиям без разрушения существующего ПО. Если некий класс содержит компонент, представляющий собой функцию без аргументов, то вполне допустимо в классах- потомках переопределить его как атрибут. (См. 'Предопределение функции в качестве атрибута', лекция 14)
Экспорт атрибутов
В завершение предшествующей дискуссии необходимо обсудить вопрос об экспорте атрибутов. Рассмотренный в этой лекции класс
Эта возможность экспорта атрибутов отличается от соглашений, принятых во многих ОО-языках. Типичным примером является Smalltalk, в котором только подпрограммы (методы) могут быть экспортированы классом, а прямой доступ к атрибутам (свойствам) запрещен.
Следуя подходу Smalltalk, доступ к атрибуту можно обеспечить только с помощью небольшой экспортированной функции, возвращающей значение атрибута. В примере класса
class POINT feature
-- Общедоступные компоненты:
abscissa: REAL is
-- Горизонтальная координата
do Result := internal_x end
ordinate: REAL is
-- Вертикальная координата
do Result := internal_y end
... Другие компоненты аналогичны предыдущей версии ...
feature {NONE}
-- Компоненты недоступные клиентам:
internal_x, internal_y: REAL
end
Этот подход имеет два недостатка:
[x]. Он побуждает авторов классов писать много маленьких функций, аналогичных
[x]. Существенное снижение производительности, так как каждое обращение к полю объекта требует вызова функции. Ничего удивительного в том, что объектная технология в некоторых кругах заработала репутацию неэффективной. Можно конечно разработать оптимизирующий компилятор, осуществляющий подстановку вместо вызова функций, но тогда какова роль таких функций?
Подход, обсуждаемый в данной лекции, представляется предпочтительным. Он избавляет от
