Php – Access protected method from child class in PHP

codeigniterinheritancePHPprotected

I can use at least two basic ways to access a protected class method from a child class:

parent::myMethod();

$this->myMethod();

If I don't need to override it in the child class, in which case I would have to do this:

function myMethod() {
   ...
   parent::myMethod();
   ...
}

which is the most recommended way to call it? I personally feel more comfortable using parent::myMethod() rather than $this->myMethod, because the first one immediately tells me this method is being inherited. But I'm not sure which way in terms of performance and best practices.

EDIT:

Check this, which is the real case of my question. It's using CodeIgniter, but even though you're not familiar with it, you will likely get it:

class Admin_Controller extends CI_Controller {

    protected function validate_form($validation) {
            $this->load->library('form_validation');
            // This will validate the form sent against the validation rules group specified in $validation
            if ($this->form_validation->run($validation) == false) {   
                    throw new Exception('There are errors in the form');
            }
    }

}

class Articles extends Admin_Controller {

    function save($id) {
            $this->validate_form(strtolower(get_class($this));
            // OR
            parent::validate_form(strtolower(get_class($this));
            // Other actions
            ....
    }

}

class Login extends Admin_Controller {

    function signIn() {
            $this->validate_form(strtolower(get_class($this));
            // OR
            parent::validate_form(strtolower(get_class($this));
            // Other actions
            ....
    }

}

Best Answer

They do two different things. The semantic of the parent keyword is such that it does a forwarding call to its parent class. The semantics of $this->method(), however, are such that it will only forward its call to the parent class in the event that the instance on which the method is called does not declare that method. It's also important to note that a child may have a parent as well as a grand parent so that must be taken into careful consideration as well in the design of the prototype.

If you don't want the method to be overridden you should use the final keyword in the method prototype declaration.

class MyClass {
    final protected function myMethod() {
    }
}

This ensures that any extending class will not be able to override the method. If an extending class attempts to override this method like the following code, you would get a fatal error of Fatal error: Cannot override final method MyClass::myMethod().

class MyOtherClass extends MyClass {
    public function myMethod() {
    }
}

Also, this makes your code more readable and less prone to error since you are clearly stating to whoever reads the code that the method is final and cannot be overridden.

Also, the underlying problem with your approach (if you want to use parent::myMethod() vs. $this->myMethod()) is that you aren't taking into account what happens when the class is a grand child of its parent, for example...

class Father {
    protected function myMethod() {
        return __METHOD__;
    }
}

class Child extends Father {
    public function myMethod() {
        return __METHOD__;
    }
}

class GrandChild extends Child {
    public function myOtherMethod() {
        echo parent::myMethod(), "\n"; // Child::myMethod
        echo $this->myMethod(), "\n";  // Child::myMethod
    }
}

$obj = new GrandChild;
$obj->myOtherMethod();

As you can see they will both give you the child method even if you meant to get at the father's method. Just declare the method as final if you never intend to override it in the extending classes and you should always be fine when calling $this->myMethod() from object context.

Related Topic