Работая с ООП нужно четко вбить в себе в голову, что перед тобой не классы, а
объекты. И разрабатывать архитектуру приложения нужно тоже с упором на это понятие.
Интерфейсы очень просто понять, для этого можно представить себе какой-то предмет с привычным для тебя названием "интерфейс". Это может быть:
- пульт от телевизора с кнопками
- сенсорная панель управления микроволновкой
- приборная панель автомобиля
- оболочка смартфона (Android, iOS, EMUI, MIUI и т.д.)
- и пр.
Всё вышеописанное - это интерфейсы взаимодействия с внутренними механизмами приборов. Интерфейсы вносят некую абстракцию. Ты не знаешь, как работает прибор внутри. У тебя может быть один интерфейс, но реализация внутреннего функционала совершенно разная. То есть, например, у тебя есть тумблер на приборной панели автомобиля, который регулирует температуру кондиционера. Но ты не знаешь, что происходит внутри, когда ты его крутишь.
Перенесемся в программирование. Этот самый тумблер - это элемент интерфейса, он запускает публичный метод
setTemperature. Это всё, что тебе нужно о нём знать.
То есть, резюмируя, интерфейсы - это декларированный абстрактный слой приложения
с доступным ограниченным набором публичных методов взаимодействия с этим приложением. Твоё приложение может и будет содержать приватные методы, ибо если используешь ООП, инкапсуляция должна быть обязательно, чтобы скрыть в чёрный ящик ненужные для пользователя механизмы. Пользователю важно понимать, что покрутив тумблер, будет изменена температура - и всё. А уж как она будет изменена - это на суд программиста.
Абстрактный класс - это по сути тот же интерфейс, но только в нём можно заранее предопределить какие-то методы, и использовать их в наследуемом классе. Абстрактные методы же нужны для того, чтобы обязательно они были реализованы в классе наследнике, ибо без них класс наследник полноценно работать не будет.
Например, есть абстрактный класс, который работает с выборкой и перегоном данных из одной БД в другую. И все методы в нём уже реализованы, кроме одного абстрактного -
getQuery, - метод, который возвращает строку с SQL запросом. Ведь запрос может быть разным и ты никогда не знаешь, какие в нем будут условия. Это какой-то абстрактный запрос, который неизвестен. И как раз под это действие очень удобно завести абстрактный метод.