Начала изучать ООП и не не могу разобраться в том, зачем нужны абстрактные классы, если есть интерфейсы.
Интерфейс, как я понимаю, нужен, грубо говоря, для следующего. Есть у нас, допустим, объекты класса Овощ. И есть интерфейс Салат, который реализует методы Мыть, Резать, Перемешать. И этот интерфейс мы можем потом применять к каким-то другим классам, если нужны будут все эти методы (например, к объектам класса Фрукт).
А вот про абстрактные классы я не понимаю, зачем они нужны, где и когда их правильно использовать. Если можно, приведите, пожалуйста, какие-то простые примеры, которые показывают, что в каком-то случае надо применять абстрактный класс, а не интерфейс.
Спасибо.
У разных языков по разному. Например в Java можно реализовывать кучу интерфейсов, но нельзя реализовать множественное наследование не больше 3-ех наследников и с помощью интерфейсов решают это.
Интерфейс нужен обычно, когда описывается только интерфейс (тавтология). Например, один класс хочет дать другому возможность доступа к некоторым своим методам, но не хочет себя "раскрывать". Поэтому он просто реализует интерфейс.
Абстрактный класс нужен, когда нужно семейство классов, у которых есть много общего. Конечно, можно применить и интерфейс, но тогда нужно будет писать много идентичного кода.
Пример: Абстрактный класс заведомо не будет запрошен как объект. К примеру абстрактный класс - Транспорт: Но все его наследники будут Автомобилем, краном, лодкой, самолет и т.д. Например вы заведомо знаете, что весь транспорт будет двигаться. И вы объявляете абстрактный метод(движение) в абстрактном классе, который нужен будет 100% всем наследникам т.е. без движения это уже не транспорт и новый наследник обязан будет реализовать это. В самом же абстрактном классе, есть другие поля и свойства, которые будут унаследованы. Ну например мощность двигателя(очень грубо), или то что их роднит.
Спасибо, вроде, очень понятное объяснение. Еще вопрос на немного другую тему, но схожую. Правильно ли я понимаю, что Транспорт нужно делать абстрактым классом (а не обычным классом) из-за того, что у него есть метод Движение и надо, чтобы все дочерние классы использовать этот метод? То есть если бы это был бы обычный класс, то в дочерних классах надо было бы писать $this->move(), а если это абстрактный класс, то метод Движение будет сразу использоваться в дочерних классах?
Анна Б: вы стучитесь в методы наследников не через абстрактный класс, а напрямую.
Вы в своем приложении создаете новый объект и используете его методы.
например
$airplains = new Airplains ; // Тут создается объект
$airpalins->getEngine(); // Тут получается свойство объекта, которое он наследовал от абстрактного класса, либо какое-то свое свойство. В моем примере это двигатель.
$airplains->move(); // тут использование метода движение, которое было унаследовано у абстрактного, но сама реализация этой функции в классе Самолет.
Самолет и Машина двигаются по разному и это "описание" пишется в методе мув, !ДЛЯ КАЖДОГО СВОЕ. Но названия метода у них одинаковые. Это позволяет передавать разные объекты и не переживать за то, что они все будут исправно работать, если вы передадите самолет он летит, если машина то она поедет. Каждый класс знает, что ему делать. Если вы не реализуете абстрактный метод в других классах, классы будут кидать ошибку и требовать от вас их реализации.
ваш код $this->move() // взять текущий объект и использовать метод мув. Если такой метод есть, а он у вас есть. То все будет окей.
Если вы делаете это не через абстрактный класс, а просто через класс. Это будет переопределение метода. На практике это выходит так: у вас есть описание как двигается самолет, а потом вы вызываете машину и машина начинает использовать тоже самое, что и самолет в итоге машина летит, а не едет.
типичный юзкейс для абстрактный классов - базовая реализация, уменьшение дублирования кода при появлении общего решения и т.д. Например у вас есть интерфейс с несколькими методами, и только 2-3 из них реализуются по разному. Выгодно вынести общую реализацию в базовый абстрактный класс.
открываем википедию: Абстрактный класс в объектно-ориентированном программировании — базовый класс, который не предполагает создания экземпляров.
Это значит: мы можем создать класс site и закидаем его всеми функциями. бесполезно делать таких 2 и больше копий..
Ну про общее назначение тут все написали, однако есть еще нюанс называемый "позднее статическое связывание", что оно такое почитайте, много букв объяснять, но весьма важный нюанс в использовании абстрактных классов.