Why can't you call abstract functions from abstract classes in PHP?
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
Comments
-
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 almost 14 yearsSick... Thanks! What is the difference between self and static? Edit: Apparently that keyword does not exist (might be a version thing).
-
Artefacto almost 14 yearsYes, this is only available on PHP 5.3.
-
philfreo about 13 yearsThe keyword instead of
self
to use isstatic
to referenceConcreteClass
in 5.3+ -
Xeoncross almost 13 yearsLSB is the main reason to use PHP 5.3. It saves more memory than any other feature implemented when used in design patterns.
-
Buffalo over 7 yearsI 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 over 7 yearsAnd, 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 over 6 yearsI removed the
static
word next tofunction
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 almost 5 yearsThank you for that!
-
saber tabatabaee yazdi almost 4 yearsInterface function App\Repositories\Banner\BannerRepository::foo() cannot contain body