56

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

1
  • 4
    LOL... static abstract... :D: cool question
    – Simon
    Commented May 18, 2010 at 17:47

3 Answers 3

98

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.

7
  • 2
    Sick... Thanks! What is the difference between self and static? Edit: Apparently that keyword does not exist (might be a version thing).
    – Cam
    Commented May 18, 2010 at 17:58
  • 1
    Yes, this is only available on PHP 5.3.
    – Artefacto
    Commented May 18, 2010 at 18:05
  • LSB is the main reason to use PHP 5.3. It saves more memory than any other feature implemented when used in design patterns.
    – Xeoncross
    Commented Jun 21, 2011 at 17:40
  • 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
    Commented Jan 19, 2017 at 13:07
  • 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. Commented Dec 6, 2017 at 3:21
8

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

1
  • 2
    The keyword instead of self to use is static to reference ConcreteClass in 5.3+
    – philfreo
    Commented Mar 19, 2011 at 1:30
0

It's a rule that abstract and static keywords can not be use on a method at the same time.

A method with an abstract keyword means that sub-class must implement it. Adding static to a method of a class allows us to use the method without instantiating it.

So that is why the error occurs.

1
  • 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.
    – Buffalo
    Commented Jan 19, 2017 at 13:09

Not the answer you're looking for? Browse other questions tagged or ask your own question.