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

    @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...
    и т.д.
    Ответ написан
    Комментировать
  • Как не коммитить изменения прав на файлы?

    denver
    @denver
    git config core.filemode false
    Ответ написан
    Комментировать