Основные принципы ООП: - Инкапсуляция - Наследование - Полиморфизм Более второстепенные: - Абстракция - Переиспользование - Посылка сообщений Инкапсуляция - важный принцип который позволяет не просто собрать до кучи поля и методы для работы с этими полями, в классе, и скрыть детали реализации. Но и разделить логику, не просто какого то определенного фрагмента кода но и в целом модуля, на внутреннюю и внешнюю, при этом что бы изменения внутри класса / модуля не влекли за собой изменения внешнего поведения. Например, есть модуль сервис(бизнес логика) и модуль для работы с данными 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. ООП