Попробуйте основательно разобраться, что такое полиморфизм, особенно одна из его разновидностей - полиморфизм типов.
Полиморфизм типов часто применяется в 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...
и т.д.