Интерфейсы и упаковка
Интерфейсы и упаковка
Herb Sutterr объяснил, что "интерфейс" класса (подразумевая, функциональные возможности, обеспечиваемые классом) включает также внешние функции, связанные с классом. Им также показано, что правила области видимости имен в C++ поддерживают эти изменения понятия "интерфейса" [7,8]. Это замечательные новости для моего тезиса "не друзья и не члены лучше, чем члены", потому что это означает, что решение сделать функцию, зависимую от класса, в виде не друга – не члена вместо члена даже не изменяет интерфейс этого класса! Кроме того, вывод функций интерфейса класса за границы определения класса ведет к некоторой замечательной гибкости упаковки, которая была бы иначе недоступна. В частности, это означает, что интерфейс класса может быть разбит на множество заголовочных файлов.
Предположим, что автор класса Wombat обнаружил, что клиенты Wombat часто нуждаются в ряде дополнительных функций, связанных, с едой, сном и размножением. Такие функции по определению не строго необходимы. Те же самые функциональные возможности могли бы быть получены через вызов других (хотя и более громоздких) методов. В результате, а также в соответствии с моим советом в этой статье, каждая дополнительная функция должна быть не другом и не методом. Но предположим, что клиенты дополнительных функций, используемых для еды, редко нуждаются в дополнительных функциях для сна или размножения. И предположим, что клиенту, использующему дополнительные функции для сна и размножения, также редко нужны дополнительные функции для еды. То же самое можно развить на функции размножения и сна.
Вместо размещения всех Wombat-зависимых функций в одном заголовочном файле, предпочтительнее было бы разместить элементы интерфейса Wombat в четырех отдельных заголовках: один для функций ядра Wombat (описания функций, связанных с определением класса), и по одному для каждой дополнительной функции, определяющей, еду, сон, и размножение. Клиенты включают в свои программы только те заголовки, в которых они нуждаются. Возникающее в результате программное обеспечение не только более ясное, оно также содержит меньшее количество зависимостей, пустых для трансляции [4,9]. Этот подход, использующий множество заголовков, был принят для стандартной библиотеки (STL). Содержание namespace std размещено в 50 различных заголовочных файлах. Клиенты включают заголовки, объявляющие только части библиотеки, необходимые им, и они игнорирует все остальное.
Кроме этого, такой подход расширяем. Когда объявления функций, составляющих интерфейс класса, распределены по многим заголовочным файлам, это становится естественным для клиентов, которые размещают свои наборы дополнительных функций, специфические для приложения, в новых заголовочных файлах, подключаемых дополнительно. Другими словами, чтобы обработать специфические для приложения дополнительные функции, они поступают точно так же, как и авторы класса. Это то, что и должно быть. В конце концов, это только дополнительные функции.