Основные принципы ООП:
- Инкапсуляция
- Наследование
- Полиморфизм
Более второстепенные:
- Абстракция
- Переиспользование
- Посылка сообщений
Инкапсуляция - важный принцип который позволяет не просто собрать до кучи поля и методы
для работы с этими полями, в классе, и скрыть детали реализации.
Но и разделить логику, не просто какого то определенного фрагмента кода но и в целом модуля,
на внутреннюю и внешнюю, при этом что бы изменения внутри класса / модуля не влекли
за собой изменения внешнего поведения.
Например, есть модуль сервис(бизнес логика) и
модуль для работы с данными DAO(data access object), где dao для сервиса
это приватное поле, но для него мы не создаем геттер, потому что тот кто будет
использовать сервис может через геттер достучатся в dao и начать ходить в БД,
то есть не инкапсулировали реализацию, в результате получается что кто то может
использовать внутренние части нижнего модуля
(где сервис по уровню абстракции лежит выше dao).
Поэтому все что касается внутренней реализации, как в примере, должно быть спрятано,
в целом не плохо как мне кажется делать таким образом, а именно лочить все поля,
то есть не стеснятся ставить private, использовать final, не спешить с геттерами и т.п.,
то есть не спешить реализовывать функционал для доступа к данным, и работать с внешней
логикой как есть, до момента пока не понадобится что то конкретное, и тогда осознанно
начать открывать то что нужно.
Наследование - возможность создавать новое, на основе старого,
где полностью или частично брать функционал и характеристики старого,
то есть на деле можно создать класс и наследоваться от другого класса и
переопределять его функционал в новом, с возможностью дописать что то новое,
или улучшить старый функционал.
В целом насколько я вычитал использование наследования предпочтительно при желании
перенести полностью весь функционал предка в новый,
например если у нас есть тип B и ему предоставить полный интерфейс типа A,
что бы тип А можно было использовать там где вполне может ожидаться тип B,
то такая схема указывает на наследование, то есть если у нас тип Ауди полностью может
продемонстрировать функционал тип Машина, если не более того,
то Ауди можно наследовать от Машина.
Но есть такое понятие как Композиция, и его не стоит убирать из внимания,
я встретил такой тезис в книге Джошуа Блоха "Предпочитайте композицию наследованию",
где суть в том что в какой то степени инкапсуляция нарушается тем что подкласс(новый)
начинает зависеть от деталей реализации суперкласса(старого).
Как определится насчет композиции, если есть тип B и вам необходимо только часть
поведения от типа A такая схема указывает на композицию, то есть например,
типу Птица может понадобится лишь полетное поведение Самолета, в таком случае,
стоит извлечь(в интерфейс/класс) такое поведение и сделать его членом обоих типов,
как Птицы так и Самолета.
То есть по факту Наследование более жесткое на фоне Композиции...
Полиморфизм - очень важное свойство в ООП, которое
позволяет не просто реализовывать функционал / объекты с одинаковым интерфейсом
и разной реализацией, примером в коде могут служить как перегруженные методы
(то есть методы с одинаковым названием но разной сигнатурой), так и
переопределенные методы.
Однако, с помощью процедурного программирования, мы не можем построить такую
архитектуру как с помощью ООП.
Речь все еще про полиморфизм.
Сила в том ;) и фишка, что мы можем любую compile time зависимость в любом месте
архитектуры развернуть в другую сторону, то есть мы можем контролировать compile time
зависимости. Если мы создадим интерфейс, его будет реализовывать модуль data, то есть
dao(модуль для работы и доступом к данным), и когда у нас уже будет работать программа,
то в runtime мы будем использовать не интерфейс а именно реализацию dao.
То есть compile time будет идти от модуля dao к модулю сервис, а run time будет идти,
в сторону от сервиса к dao.
Нам важно контролировать compile time зависимости, потому что нам важно контролировать
код, и мы не можем себе позволить зависеть от реализации(dao) в таком случае.
То есть суть в таком подходе и использовании полиморфизма, в том что бы проектировать
дизайн так, что бы модули высшего порядка не зависели от модулей низшего, то есть
модули с бизнес логикой не зависели от деталей реализации модулей dao.
Если в каком то месте нужно забрать зависимость compile time от какого то модуля,
мы просто можем использовать такой подход, то есть развернуть зависимость в другую
сторону. Но еще нужно думать когда так следует делать, то есть когда зависеть от
абстракции а когда от реализации, но главное понимать что полиморфизм в ООП дает нам
такую возможность.
Где в процедурном программировании реализовать такую фишку сложнее, и опаснее...
№1. ООП
sectumsempra
21 уровень
№2. Принципы ООП.
Комментарии (2)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Сергей Я Java Developer в DXC/Luxoft Expert
27 ноября, 19:31
Все подробно описано ВОТ ТУТ с историей и примерами
0
sectumsempra
27 ноября, 19:57
Спасибо за ссылку, очень полезная.
0