Godwin
Godwin

Reputation: 9907

Calling parent method of inherited class from base class

The following example does not work because when parent is called in class A, php looks for the parent class of class A but it doesn't exist. I would rather this line to call Test() in class B.

Is this possible?

(I know this seems like a stupid example but it has a practical application)

abstract class A {
    function CallParentTest()
    {
        return call_parent_method('Test');
    }
}

abstract class B extends A {
    function Test()
    {
        return 'test passed';
    }
}

class C extends B {
    function Test()
    {
        return $this->CallParentTest();
    }
}

$object = new C();
echo $object->Test();

Thanks!

EDIT
I changed the parent keyword to the made up method call_parent_method because I think that may have been confusing people. I know there is no way to do this using the keyword.

Just as David Harkness pointed out, I am trying to implement the Template Method pattern but instead of using two different method names, I'm using one. B::Test() will be the default method unless substituted with alternate functionality.

Upvotes: 6

Views: 6235

Answers (3)

David Harkness
David Harkness

Reputation: 36532

You can use reflection to bypass the natural calling order for overridden methods. In any context simply create a ReflectionMethod for the method you'd like to call and invoke it. You don't need to do this from the class itself, but you will need to call setAccessible(true) if the method isn't public.

class A {
    public function bypassOverride() {
        echo "Hi from A\n";
        $r = new ReflectionMethod('B', 'override');
        $r->invoke($this);
    }
}

class B extends A {
    public function override() {
        echo "Hi from B\n";
    }
}

class C extends B {
    public function override() {
        echo "Hi from C\n";
        $this->bypassOverride();
    }
}

$c = new C;
$c->override();

The output from this is

Hi from C
Hi from A
Hi from B

You could make bypassOverride() more generic and move it to a helper class if you need to do this a lot.

Upvotes: 6

David Harkness
David Harkness

Reputation: 36532

webbiedave is correct regarding parent, but it looks like you're trying to implement the Template Method pattern where the abstract base class calls a method that subclasses are expected to implement. Here's an example that demonstrates a horrible way to handle errors in your applications.

abstract class ExceptionIgnorer {
    public function doIt() {
        try {
            $this->actuallyDoIt();
        }
        catch (Exception $e) {
            // ignore the problem and it might go away...
        }
    }

    public abstract function actuallyDoit();
}

class ErrorThrower extends ExceptionIgnorer {
    public function actuallyDoIt() {
        throw new RuntimeException("This will be ignored");
    }
}

$thrower = new ErrorThrower;
$thrower->doIt(); // no problem

Here doIt() is the template method as it defines the overall algorithm to follow.

Upvotes: 1

webbiedave
webbiedave

Reputation: 48897

Is this possible?

No.

It makes no sense to use the parent keyword except in child classes. It's only purpose is to be used by child classes to call methods that it as overridden. Think about multi-level parent calls where a child calls its parent's method of the same name and, in turn, that parent calls its parent's method of the same name.

Upvotes: 1

Related Questions