Why can't you call abstract functions from abstract classes in PHP?

25,364

Solution 1

This is a correct implementation; you should use static, not self, in order to use late static bindings:

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();

gives the expected "bar".

Note that this is not really polymorphism. The static keywork is just resolved into the class from which the static method was called. If you declare an abstract static method, you will receive a strict warning. PHP just copies all static methods from the parent (super) class if they do not exist in the child (sub) class.

Solution 2

You notice that word self?

That is pointing to AbstractClass. Thus it is calling AbstractClass::foo(), not ConcreteClass::foo();

I believe PHP 5.3 will provide late static bindings, but if you are not on that version, self will not refer to an extended class, but the class that the function is located in.

See: http://us.php.net/manual/en/function.get-called-class.php

Share:
25,364
Cam
Author by

Cam

Software engineer

Updated on July 09, 2022

Comments

  • Cam
    Cam almost 2 years

    I've set up an abstract parent class, and a concrete class which extends it. Why can the parent class not call the abstract function?

    //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();
    ?>
    

    Error:

    Fatal error: Cannot call abstract method AbstractFoo::foo() in foo.php on line 5

  • Cam
    Cam almost 14 years
    Sick... Thanks! What is the difference between self and static? Edit: Apparently that keyword does not exist (might be a version thing).
  • Artefacto
    Artefacto almost 14 years
    Yes, this is only available on PHP 5.3.
  • philfreo
    philfreo about 13 years
    The keyword instead of self to use is static to reference ConcreteClass in 5.3+
  • Xeoncross
    Xeoncross almost 13 years
    LSB is the main reason to use PHP 5.3. It saves more memory than any other feature implemented when used in design patterns.
  • Buffalo
    Buffalo over 7 years
    I had a case of PHP failing to reach the implementation of a abstract static method in my class (implemented in a subclass) - solved it with "static::".
  • Buffalo
    Buffalo over 7 years
    And, yet, they can be used. An example would be using PHPUnit's static setUpBeforeClass() with values depending on subclasses - you'd need an abstract (so the subclasses implement it in the first place and also differently) static (so you can call it from setUpBeforeClass()) method.
  • daniel souza
    daniel souza over 6 years
    I removed the static word next to function from both child and abstract classes. return static::foo(); whas the correct answer. So the superclass can bind to the child class implementation of abstract function. PHP version 5.6.
  • Severin
    Severin almost 5 years
    Thank you for that!
  • saber tabatabaee yazdi
    saber tabatabaee yazdi almost 4 years
    Interface function App\Repositories\Banner\BannerRepository::foo() cannot contain body