Мейер [19] и Снайдерс [20] высказали идею контрактного программирования:
большие задачи надо разделить на много маленьких и перепоручить их мелким субподрядчикам. Нигде эта идея не проявляет себя так ярко, как в проектировании классов.
По своей природе, класс - это генеральный контракт между абстракцией и всеми ее клиентами. Выразителем обязательств класса служит его интерфейс, причем в языках с сильной типизацией потенциальные нарушения контракта можно обнаружить уже на стадии компиляции.
Идея контрактного программирования приводит нас к разграничению внешнего облика, то есть интерфейса, и внутреннего устройства класса, реализации. Главное в интерфейсе - объявление операций, поддерживаемых экземплярами класса. К нему можно добавить объявления других классов, переменных, констант и исключительных ситуаций, уточняющих абстракцию, которую класс должен выражать. Напротив, реализация класса никому, кроме него самого, не интересна. По большей части реализация состоит в определении операций, объявленных в интерфейсе класса.
Мы можем разделить интерфейс класса на три части:
открытую (public) - видимую всем клиентам;
защищенную (protected) - видимую самому классу, его подклассам и друзьям (friends);
закрытую (private) - видимую только самому классу и его друзьям.
Разные языки программирования предусматривают различные комбинации этих частей. Разработчик может задать права доступа к той или иной части класса, определив тем самым зону видимости клиента.
В частности, в C++ все три перечисленных уровня доступа определяются явно. В дополнение к этому есть еще и механизм друзей, с помощью которого посторонним классам можно предоставить привилегию видеть закрытую и защищенную области класса. Тем самым нарушается инкапсуляция, поэтому, как и в жизни, друзей надо выбирать осторожно. В Ada объявления могут быть сделаны закрытыми или открытыми. В Smalltalk все переменные - закрыты, а методы - открыты. В Object Pascal все поля и операции открыты, то есть никакой инкапсуляции нет [Речь идет о старых версиях Object Pascal - Прим.