PHP: Полиморфизм
Теория: Полиморфизм подтипов
До сих пор мы работали с так называемой утиной типизацией: Если что-то ходит как утка и крякает как утка, то это и есть утка. Она проявляется в том, что в сигнатуре функции не указывается ожидаемый класс или интерфейс объекта. Мы просто ждём, что вызывающий код отдаст объект, имеющий необходимые методы:
Утиная типизация автоматически вытекает из динамической типизации. В большинстве динамических языков понятия "интерфейс" даже не существует. PHP в этом смысле пошёл своим путём. Несмотря на его динамическую природу, классовая модель PHP взята из Java. И в PHP присутствуют почти все соответствующие атрибуты: интерфейсы, абстрактные классы и многое другое. Поэтому в PHP принято указывать интерфейсы ожидаемых объектов в сигнатурах функций.
Теперь эта функция работает только с объектами тех классов, которые реализуют указанный интерфейс.
Как вы помните, в сигнатуре можно указывать и класс, и интерфейс. Что правильнее? Вооружившись принципом инверсии зависимостей, мы можем однозначно сказать, что правильнее использовать интерфейсы и завязываться на абстракцию вместо конкретной реализации. Только в этом случае появится возможность подменить реализацию. Ниже пример реального кода из фреймворка Symfony2, в котором активно используется полиморфизм подтипов с инъекцией через конструктор:
В очередной раз подчеркну что не нужно возводить эту технику в абсолют. Если создавать интерфейсы на всё подряд, то код очень быстро распухнет и станет сложным. Вспомните, в ruby/python/js вообще нет интерфейсов и никто не умер. Попробуйте побродить по исходникам популярного микрофреймворка Lumen. Внутри него крайне тяжело найти места, где в сигнатурах методов встречаются явные указания интерфейсов
Для лучшей переносимости кода, в PHP вводятся стандартные интерфейсы для самых частых задач. Они описываются в PSR. В примере выше используется стандартный интерфейс Psr\Log\LoggerInterface. Со временем, всё большая часть библиотек начнёт его реализовывать, а это позволит безболезненно подменять логгер без необходимости менять свой код. Кроме логгера в PSR описаны множество других интерфейсов, среди них HTTP-клиент, HTTP-запрос, HTTP-ответ, кеш и другое.
Теперь мы можем ответить на вопрос, почему этот полиморфизм называется полиморфизмом подтипов. Типом в ООП языках принято называть интерфейсы (хотя это не совсем правда) и отношение подтипов определяется отношением интерфейсов.
Интерфейсы можно расширять другими интерфейсами, для этого используется ключевое слово extends. Пример из библиотеки DS (той, где описаны структуры данных на PHP в объектном синтаксисе):
Теперь любой класс, реализующий интерфейс Collection, будет обязан реализовать все интерфейсы, которые расширяет Collection. Это касается каждого интерфейса в цепочке.
Статические методы
Статические методы жёстко завязаны на имя класса, поэтому полиморфизм подтипов в них невозможен. Но можно схитрить и использовать вместо класса переменную с его именем:
.png)

