Это правильная реализация; вы должны использовать static, а не self, чтобы использовать поздние статические привязки :
abstract class AbstractFoo{
public static function foo() {
throw new RuntimeException("Unimplemented");
}
public static function getFoo(){
return static::foo();
}
}
class ConcreteFoo extends AbstractFoo{
public static function foo(){
return "bar";
}
}
echo ConcreteFoo::getFoo();
дает ожидаемый "бар".
Обратите внимание, что это на самом деле не полиморфизм. Статическая клавиатурная обработка просто преобразуется в класс, из которого был вызван статический метод. Если вы объявите абстрактный статический метод, вы получите строгое предупреждение. PHP просто копирует все статические методы из родительского (супер) класса, если они не существуют в дочернем (под) классе.