Stasgar
@Stasgar
Обученная макака

Для чего используют абстрактные классы?

Вот допустим шаблон кода, которым везде пытаются объяснить полезность абстрактных классов:
abstract class ClassName
{
    abstract public function doSomething($something);
//не абстрактные методы
}

class ChildClass extends ClassName
{
    public function doSomething($something)
    {
        //code
    }
}


Так вот, в чем смысл использовать такую конструкцию, если можно сделать так:
class ClassName
{

//не абстрактные методы
}

class ChildClass extends ClassName
{
    public function doSomething($something)
    {
        //code
    }
}


Для чего это нужно? И в каких примерах? В гугле все примеры - подобны тому, что скинул сверху, т.е. бессмысленны.

Пока единственное, что приходит на ум - дать понимание другому программисту, что использовать наследование нужно обязательно с такими-то методами.
  • Вопрос задан
  • 2505 просмотров
Решения вопроса 3
Denormalization
@Denormalization
1) Нельзя создать инстанс абстрактного класса.
2) Методы объявленные как "abstract" - обязательны к реализации. Что дает уверенность в том, что любой наследник будет реализовывать эти методы.
3) Открыв файл с абстрактным классом, я сразу вижу методы которые у него есть, и которые мне необходимо реализовать. В вашем же примере я не знаю какие методы относятся конкретно к ChildClass, а какие к ClassName.

Все эти интерфейсы, абстрактные классы и т.д и т.п нужно тогда, когда над проектом работает несколько (много) человек, и проект чуть больше чем "свой мегакрутой бложик".
Ответ написан
Комментировать
@Firik67
Middle PHP Developer
Это нужно для гарантии того, что в наследуемых классах будет реализован метод с тем же названием и похожим функционалом. Например, у классов Треугольник и Круг должен быть реализован абстрактный метод get_area, который считает площадь. Иначе можно писать в одном классе area, в другом get_area, что вызывает путаницу и проблемы с поддержкой кода. Имхо, думаю это не вся суть:)
Ответ написан
ThunderCat
@ThunderCat Куратор тега PHP
{PHP, MySql, HTML, JS, CSS} developer
Абстрактный класс - это шаблон проектировщика, если вы наследуете от него класс, то он ОБЯЗАН иметь реализацию всех абстрактных методов какие перечислены в абстракции. Если Вася наследует от базовой абстракции MultiMedia класс Video, а Коля класс Audio, то для них будет "подсказка" что в их классе обязательно должен быть метод getPlayTime(), который есть в абстрактном классе, и Федя может смело его вызывать в любом классе наследуемом от абстрактного. Хотя в video и audio они реализованы по разному.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@xfg
Попробуйте основательно разобраться, что такое полиморфизм, особенно одна из его разновидностей - полиморфизм типов.

Полиморфизм типов часто применяется в php. Вот его суть на вашем примере:

abstract class ClassName
{
    abstract public function doSomething($something);
//не абстрактные методы
}

class ChildClass extends ClassName
{
    public function doSomething($something)
    {
        //code
    }
}

class Main {
  public run(ClassName $class) {
    //code
  }
}

$obj = new Main();
$obj->run(new ChildClass());

Метод в Main::run() параметризован, его параметр $class теперь может соответствовать только дочерним классам вашего абстрактного класса ClassName.

Зачем это нужно?
Это нужно тогда, когда у вас может быть несколько реализаций одного и того же компонента. И вы точно знаете, что в будущем вам может понадобиться другая реализация. Например, представьте себе класс кеширования. Согласитесь, что кешировать можно в файл, можно в базу, можно в память и т.д. В таком случае, вы можете выделить абстракцию Cache с общим функционалом для любой реализации и создать наследников CacheFile, CacheMysql, CacheRedis и т.д.

Теперь когда вам понадобится компонент кеша, то вы можете внедрить его через параметр метода, который параметризирован типом Cache, если такому методу дать что-то другое, то интерпретатор кинет исключение. Вы же получаете гибкость. В любое время вы можете заменить реализацию компонента кеша на другой, просто передав в метод другой дочерний объект абстрактного класса Cache. Вы уже точно знаете, какой у него должен быть контракт и точно знаете, что вам не нужно вносить исправления в тот метод, который использует ваш класс Cache. Вы молодцы, ведь вы только что применили полиморфный принцип открытости/закрытости, одного из принципов SOLID а это значит, что ваш код стал чуть лучше.

Но, скорее всего, если вы ничего об этом не слышали, то вам следует обязательно познакомиться с Dependency injection container, который будет внедрять нужный компонент автоматически, вместо вас. Вы же лишь будете указывать в конфигах, какую именно реализацию компонента нужно подавать всему остальному коду. Тогда весь ваш проект сможет переезжать с CacheFile на CacheRedis и наоборот с помощью изменения всего одной строчки в конфиге.

Также, если у компонента нет общей реализации, которую можно вынести в абстрактный класс, то вместо него, стоит использовать интерфейс. Идея остается. Полиморфно замещать различные реализации.

Помимо примеров в гугле, смотрите еще и живой код open source проектов.
https://github.com/yiisoft/yii2/blob/master/framew...
https://github.com/yiisoft/yii2/blob/master/framew...
https://github.com/yiisoft/yii2/blob/master/framew...
и т.д.
Ответ написан
Комментировать
Инкапсуляция, полиморфизм и т.п.
Точные термины не помню.

Можно одинаково работать с разными объектами, если видеть в них только базовый класс.
Ответ написан
VladimirAndreev
@VladimirAndreev
php web dev
вот пишешь ты драйвера базы данных.
соответственно, у тебя должен быть абстрактный класс драйвера. который заставляет потомков реализовать некоторый набор методов, в свою очередь, для некоторых операций может какую-то реализацию предложить.

и потом, есть у тебя допустим модель, которой требуется, чтобы ей передали драйвер базы данных.
если у тебя есть абстрактный класс - ты можешь написать так: function __construct(Db_Driver $driver);
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы