
Дисклеймер. Эта статья не является призывом к действию и не утверждает, что есть единственный рассово верный способ сокрыть данные. Эта статья сделана с целью предложить читателю, возможно, новый взгляд на инкапсуляцию. Существует много ситуаций, где модификаторы доступа предпочтительней, однако это не повод умалчивать об интерфейсах.
В общем виде инкапсуляция определяется как средство сокрытия внутренней реализации объекта от клиента с целью сохранения целостности объекта и сокрытия сложности этой самой внутренней реализации.
Добиться такого сокрытия можно несколькими способами. Одним является использование модификаторов доступа, другим — использование интерфейсов (протоколов, заголовочных файлов, …). Есть и другие хитрые возможности, но статья не о них.
Модификаторы доступа на первый взгляд могут показаться более мощным средством с точки зрения сокрытия реализации, поскольку дают контроль над каждым полем в отдельности и дают больше опций доступа. В действительности же это отчасти просто шорткат для создания нескольких интерфейсов к классу. Модификаторы доступа дают возможности не шире, чем интерфейсы, поскольку с помощью них выражаются, кроме одной детали. О ней ниже.

Видимость полей, обозначенный разными модификаторами доступа в Java.
В фрагменте кода ниже представлен класс с модификаторами доступа к методам и эквивалетные представления в виде интерфейсов.
public class ConsistentObject { public void methodA() { /* ... */ } protected void methodB() { /* ... */ } void methodC() { /* ... */ } private void methodD() { /* ... */ } } public interface IPublicConsistentObject { void methodA() { /* ... */ } } public interface IProtectedConsistentObject: IPublicConsistentObject { void methodB() { /* ... */ } } public interface IDefaultConsistentObject: IProtectedConsistentObject { void methodC() { /* ... */ } }
Протоколы имеют ряд преимуществ. Достаточно упомянуть то, что это основное средство реализации полиморфизма в ООП, которое доходит до новичков сильно позже, чем могло бы.
Единственная сложность подходя с протоколами состоит в том, что надо контролировать процесс создания объектов. Порождающие шаблоны нужны именно для того чтоб оградить опасный код, содержащий конкретные типы от чистого кода, работающего с интерфейсами. Соблюдая это простое правило, мы получаем ту же самую инкапсуляцию, что и использованием спецификаторов, но при этом получаем большую гибкость.
Такой код на C#
public class DataAccessObject { private void readDataFromFixedSource() { // ... } public byte[] getData() { // ... } }
будет эквивалентен такому по возможностям для клиента.
public class DataAccessObjectFactory { public IDataAccessObject createNew() { return new DataAccessObject(); } } public interface IDataAccessObject { byte[] getData(); } class DataAccessObject: IDataAccessObject { void readDataFromFixedSource() { // ... } public byte[] getData() { // ... } }
Из-за существования модификаторов доступа, новички очень долго не узнают об интерфейсах. От этого они не пользуются настоящей мощью ООП. То есть происходит некоторая подмена понятий. Модификаторы доступа — несомненно атрибут ООП, но они же перетягивает одеяло с интерфейсов, которые раскрывают ООП гораздо сильнее.
Более того, интерфейсы заставляют осознанно выбирать какие возможности от объекта может получать какой клиент. То есть у нас есть возможность предоставить абсолютно несвязанные протоколы для разных клиентов, тогда как модификаторы не различают клиентов. Это большой плюс в пользу интерфейсов.
ссылка на оригинал статьи https://habr.com/ru/post/477142/
Добавить комментарий