Эта статья продолжает цикл материалов об объектно-ориентированном программировании. Если вы ещё не ознакомились с введением в ООП, следует это сделать.
Инкапсуляция – это одна из "легких" концепций ООП, которую можно понять сразу. Как следует из названия, это "помещение в капсулу". А также можно назвать это изоляцией или сокрытием.
Иногда её понимают по-разному, я постараюсь охватить все случаи.
Во-первых, инкапсуляцию мы применили сразу же, как создали объект.
Смотрите: есть несколько переменных и функций, которые мы собрали вместе и сделали свойствами и методами объекта. Теперь они отделены от всего остального программного кода "капсулой" объекта, то есть – инкапсулированы.
Во-вторых, когда мы вызываем метод объекта снаружи, то нам неважно, какой код, и насколько большой и сложный, написан в этом методе. Мы видим, что у объекта есть метод, мы передаем туда какие-то данные и получаем результат. Это тоже инкапсуляция.
Наконец, третье значение инкапсуляции – сокрытие. Давайте вернемся к предыдущему примеру про объект, который представляет собой банковский счет.
У этого объекта есть свойство sum, которое соответствует сумме на счету. Я говорил, что нельзя просто так взять и присвоить какое-то число этому свойству. Потому что перед этим надо проверить несколько условий, ведь никому не понравится, если у него на счету окажутся миллионы долларов некорректные данные.
Для этого объекту был добавлен метод add_sum(), который и осуществляет все проверки, и только после этого изменяет сумму. И работать со счетом можно только через этот метод.
И тут возникает вопрос: а почему "только"? Ну ладно, появился метод, но свойство sum никуда ведь не исчезло, и его можно по-прежнему присвоить напрямую.
Да, это так. Именно поэтому было придумано сокрытие свойств (и методов тоже). Для этого в определении класса нужно прямо указывать, какой доступ у каждого свойства: публичный (public) или приватный (private). Если публичный, то его можно и прочитать, и записать снаружи, оно видно всем. Если приватный, то его видит только сам объект. Если попытаться присвоить его снаружи, то возникнет ошибка. Объявив свойство sum приватным, мы надежно спрячем его от внешних посягательств, и доступ к нему теперь будет возможен только через метод add_sum(). Как всегда, код без привязки к конкретному языку:
Также приватными могут быть любые свойства объекта, которые нужны только ему самому и больше никому снаружи, и методы, которые может вызывать только сам объект у себя, и никто снаружи.
Надо понимать, что таким образом мы прячем доступ к свойствам и методам объекта не от каких-то злых хакеров (хотя хакерам лучше не давать никаких возможностей), а от самих себя. Да, инкапсуляция применяется для того, чтобы ленивый программист (мы же помним, что он ленивый) не "пошел в обход", не забыл чего-нибудь и т.д. Также она важна в условиях, когда код очень большой и его пишут несколько программистов. Они могут не разбираться в тонкостях реализации объектов, написанных другими. Поэтому каждый заботится о том, чтобы объект, написанный им, мог использоваться только корректным образом, и скрывает всё то, что не должно вылезать наружу.
Короче говоря, сокрытие связано в основном с самодисциплиной и порядком. В некоторых языках сокрытия нет вообще. У всех объектов все свойства и методы всегда публичные. Поэтому там можно надеяться только на себя.
И ещё одно замечание. Приватные свойства и методы такие приватные, что даже не наследуются потомками класса. Чтобы свойство можно было наследовать, и при этом оставить его приватным, была сделана дополнительная категория – "защищенное" (protected). Защищенные свойства для внешнего мира всё так же не видны, но вот потомки класса, и только этого класса, видят их через своего родителя. Можно сказать, что к приватным свойствам имею доступ только я сам, к защищенным – я и мои дети, а к публичным – я, мои дети и весь мир.
Вот и всё про инкапсуляцию!