Инкапсуляция и абстракция — два из четырех столпов объектно-ориентированного программирования. Оба принципа помогают проектировать класс таким образом, чтобы он мог выполнять необходимые функции, а также не раскрывал нежелательные детали другим классам, чтобы избежать их неправильного использования.
В этой статье мы подробно рассмотрим абстракцию и инкапсуляцию, а также обсудим несколько различий между ними.
1. Инкапсуляция простыми словами
Проще говоря, помещение данных(состояния) и методов(поведения) внутрь класса в сочетании с сокрытием информации и реализации(посредством контроля доступа ) называется инкапсуляцией.
Результатом инкапсуляции является класс с характеристиками и поведением. Он может взаимодействовать с другими классами в приложении для выполнения любой бизнес-операции.
В следующем примере класс ReportWriter имеет атрибут defaultLocation, к которому можно получить доступ через публичные методы setter и getter. Он предотвращает прямую установку атрибута, делая его закрытым.
ReportWriter также предоставляет метод writeReport(), который сгенерирует отчет в текущем расположении по умолчанию, установленном в атрибуте defaultLocation. Это пример инкапсуляции.
class ReportWriter {private String defaultLocation;public String getDefaultLocation() {return defaultLocation;}public void setDefaultLocation(String defaultLocation) {if(defaultLocation != null)this.defaultLocation = defaultLocation;}public void writeReport(String reportType) {//...}}
2. Все изменения следует инкапсулировать.
Я где-то прочитал: «Что бы ни изменилось, инкапсулируй это». Это цитировалось как известный принцип проектирования. Если на то пошло, в любом классе изменения могут произойти в данных во время выполнения, а изменения в реализации могут произойти в будущих выпусках. Таким образом, инкапсуляция применима как к данным, так и к реализации.
Контроль доступа или сокрытие реализации устанавливает границы внутри типа данных или класса по двум важным причинам.
- Установление того, что могут использовать другие классы, а что нет.
- Отделить интерфейс от реализации.
В любом классе, если мы можем гарантировать, что другие классы не могут делать ничего, кроме отправки сообщений через публичные методы, то мы можем изменять непубличные члены класса в будущем, не беспокоясь и не нарушая клиентский код. Инкапсуляция помогает нам в достижении этой уверенности.
3. Что такое абстракция?
Абстракция — это возможность создавать абстрактные акторы в системе, которые могут выполнять работу, сообщать и изменять свое состояние, а также общаться с другими объектами в системе. Абстрактный актор означает, что мы знаем, как работать с объектом, но не знаем, как он работает внутри. Он скрывает детали своей реализации с помощью модификаторов доступа.
Для работы с такими абстрактными акторами нам нужно знать только о публичных API, которые мы будем использовать. Нам не нужно заботиться о том, как они выполняют свою работу.
Например, в предыдущем примере ReportWriter мы определили метод writeReport(), который клиенты должны использовать для генерации отчетов. Клиенты не должны беспокоиться о том, как генерируются отчеты.
class ReportWriter {public void writeReport(String reportType) {//...}}
4. Разница между инкапсуляцией и абстракцией
Изучая абстракцию, мы узнали, что абстракция по сути является идеей, которая помогает абстрагировать поведение класса. Инкапсуляция — это механизм, с помощью которого мы реализуем желаемую абстракцию.
Короче говоря, с точки зрения ООП можно сказать, что:
- Абстракция больше касается того, «что» класс может делать. [Идея]
- Инкапсуляция больше касается того, «как» достичь этой функциональности. [Реализация]
Возьмем в пример известный класс HashMap. Класс HashMap отвечает за хранение пар ключ-значение, поиск по ключам и многое другое.
Извне клиентский код знает только свои методы get() и put(). Они вызывают эти методы и живут счастливо. По сути, это абстракция. Абстракция говорит, что клиентский код должен вызвать метод для добавления пары ключ-значение, метод для извлечения значения на основе ключа и т. д. То, как это должно быть сделано, не касается клиентского кода.
Инкапсуляция — это когда мы реализуем класс HashMap и пишем эти методы. Мы пишем класс HashMap.Entry и создаем таблицу переменных типа Entry[]. Затем мы объявляем все эти вещи закрытыми и даем открытый доступ только методам put() и get() и т. д. Это на самом деле инкапсуляция.
Инкапсуляция — это реализация желаемой абстракции.