Reputation: 63646
abstract class base {
abstract public function test();
public function run()
{
self::test();
}
}
class son extends base {
public function test()
{
echo 1;
}
}
son::run();
It reports:
Fatal error: Cannot call abstract method base::test()
But son::test()
works,why and is there a way to fix?
Upvotes: 0
Views: 346
Reputation: 316979
Of course:
Fatal error: Cannot call abstract method base::test()
It has no method body you could call. If run() is supposed to be a Template Method, you refer to the class scope with $this
instead of self
and then create an instance of $son to call run() on it, e.g.
abstract class BaseClass {
abstract public function test();
public function run()
{
$this->test();
}
}
class Son extends BaseClass {
public function test()
{
echo 1;
}
}
$son = new Son;
$son->run(); // 1
which is rather odd, because then you could have just as well called test() directly.
Also note that in your example
son::run();
is wrong, because the run() method is not declared static and while PHP will execute run() nonetheless, it is considered wrong usage and will raise an E_STRICT error. However, if you were to define run() static, you could no longer reference $this
, because a static method is not invoked from instance scope, but class scope.
Edit I was about to add the PHP5.3 solution, but see that @erenon already did that, while I was typing, so I only add the appropriate reference in the PHP Manual on Late Static Binding.
Upvotes: 4
Reputation: 53940
"self" is lexically scoped, that is, if you use "self" in a method of Base, "self" means "Base", no matter how you call this method at run time. php5.3 introduced a new kind of dynamic binding, which, ironically enough, is called "static". The following works as expected in php 5.3
abstract class base {
abstract public static function test();
static public function run()
{
static::test();
}
}
class son extends base {
static public function test()
{
echo 1;
}
}
son::run();
Upvotes: 4
Reputation: 19118
Factory/singleton pattern mix:
class Base
{
static private $instance;
static function getSon() {
if (null === self::$instance) {
self::$instance = new Son;();
}
return self::$instance;
}
}
class Son
{
public function test() {
echo 1;
}
}
Base::getSon()->test(); //1
Upvotes: 1
Reputation: 134167
Abstract methods do not have an implementation, and thus cannot be called. If the method is not defined as abstract, and actually has an implementation, then it can be executed by your code. For example:
public function test(){
echo "Hello from base!";
}
Upvotes: 1