Стандарты программирования на С++. 101 правило и рекомендация | страница 73
>File
, >Date
, >BankAccount
, >Security
) должны закрывать все данные-члены и открывать соответствующие интерфейсы. Позволение вызывающему коду непосредственно работать с внутренними данными класса работает против представленной им абстракции и поддерживаемых им инвариантов.Агрегат >Node
, широко используемый в реализации класса >List
, обычно содержит некоторые данные и два указателя на >Node
: >next_
и >prev_
. Данные-члены >Node
не должны быть скрыты от >List
. Однако не забудьте рассмотреть еще пример 3.
Пример 2. TreeNode. Рассмотрим контейнер >Tree
, реализованный с использованием >TreeNode
, агрегата, используемого в >Tree
, который хранит указатели на предыдущий, следующий и родительский узлы и сам объект >T
. Все члены >TreeNode
могут быть открытыми, поскольку их не надо скрывать от класса >Tree
, который непосредственно манипулирует ими. Однако класс >Tree
должен полностью скрывать класс >TreeNode
(например, как вложенный закрытый класс или как определенный только в файле реализации класса >Tree
), поскольку это — детали внутренне реализации класса >Tree
, от которых не должен зависеть и с которыми не должен иметь дела вызывающий код. И наконец, >Tree
не скрывает содержащиеся в контейнере объекты >T
, поскольку за них отвечает вызывающий код; контейнеры используют абстракцию итераторов для предоставления доступа к содержащимся объектам, в то время как внутренняя структура контейнера остается скрытой.
Пример 3. Функции получения и установки значений. Если не имеется лучшей предметной абстракции, открытые и защищенные данные-члены (например, >color
) могут, как минимум, быть сделаны закрытыми и скрыты за функциями получения и установки значений (например, >GetColor
, >SetColor
). Тем самым обеспечивается минимальный уровень абстракции и устойчивость к изменениям.
Использование функций повышает уровень общения по поводу "цвета" от конкретного состояния до абстрактного, которое мы можем реализовать тем способом, который сочтем наиболее приемлемым. Мы можем изменить внутреннее представление цвета, добавить код для обновления дисплея при изменении цвета, добавить какие-то инструментальные средства или внести еще какие-то изменения — и все это без каких-либо изменений в вызывающем коде. В худшем случае вызывающий код потребуется перекомпилировать (т.е. мы сохраняем совместимость на уровне исходных текстов); в лучшем — не потребуется ни перекомпиляция, ни даже перекомпоновка (если изменения сохраняют бинарную совместимость). Ни совместимость на уровне исходных текстов, ни бинарная совместимость при внесении таких изменений невозможны, если исходный дизайн содержит открытый член