Почему вы не можете называть абстрактные функции абстрактными классами в PHP?

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

//foo.php
<?php
    abstract class AbstractFoo{
        abstract public static function foo();
        public static function getFoo(){
            return self::foo();//line 5
        }
    }

    class ConcreteFoo extends AbstractFoo{
        public static function foo(){
            return "bar";
        }
    }

    echo ConcreteFoo::getFoo();
?>

Ошибка:

Неустранимая ошибка: не удается вызвать абстрактный метод AbstractFoo:: foo() в foo.php в строке 5

Ответ 1

Это правильная реализация; вы должны использовать 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 просто копирует все статические методы из родительского (супер) класса, если они не существуют в дочернем (дочернем) классе.

Ответ 2

Вы заметили, что слово self?

Это указывает на AbstractClass. Таким образом, он вызывает AbstractClass:: foo(), а не ConcreteClass:: foo();

Я считаю, что PHP 5.3 обеспечит поздние статические привязки, но если вы не в этой версии, я не буду ссылаться на расширенный класс, а на класс, в котором находится эта функция.

Смотрите: http://us.php.net/manual/en/function.get-called-class.php

Ответ 3

Это правило, что ключевые слова abstract и static не могут использоваться в методе одновременно.

Метод с ключевым словом abstract означает, что подкласс должен его реализовать. Добавление static в метод класса позволяет использовать метод без его экземпляра.

Вот почему возникает ошибка.