从PHP中的子类访问受保护的方法

Lui*_*tin 3 php inheritance codeigniter protected

我可以使用至少两种基本方法从子类访问受保护的类方法:

parent::myMethod();

$this->myMethod();
Run Code Online (Sandbox Code Playgroud)

如果我不需要在子类中重写它,在这种情况下我将不得不这样做:

function myMethod() {
   ...
   parent::myMethod();
   ...
}
Run Code Online (Sandbox Code Playgroud)

这是最推荐的方式吗?我个人觉得使用parent :: myMethod()而不是$ this-> myMethod更舒服,因为第一个立即告诉我这个方法是继承的.但我不确定哪种方式在性能和最佳实践方面.

编辑:

检查一下,这是我的问题的真实案例.它使用CodeIgniter,但即使你不熟悉它,你也可能会得到它:

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
            ....
    }

}
Run Code Online (Sandbox Code Playgroud)

She*_*rif 5

他们做了两件不同的事情.parent关键字的语义是这样的,它对其父类进行转发调用.$this->method()但是,语义只有在调用方法的实例不声明该方法的情况下才会将其调用转发给父类.同样重要的是要注意,孩子可能有父母以及父母,因此在原型设计中也必须仔细考虑.

如果您不希望覆盖该方法,则应在方法原型声明中使用final关键字.

class MyClass {
    final protected function myMethod() {
    }
}
Run Code Online (Sandbox Code Playgroud)

这可确保任何扩展类都无法覆盖该方法.如果扩展类尝试覆盖此方法,如下面的代码,您将收到致命错误Fatal error: Cannot override final method MyClass::myMethod().

class MyOtherClass extends MyClass {
    public function myMethod() {
    }
}
Run Code Online (Sandbox Code Playgroud)

此外,这使您的代码更具可读性,并且更不容易出错,因为您明确地告诉那些读取代码的人,该方法是最终的并且无法被覆盖.

此外,您的方法的潜在问题(如果您想使用parent::myMethod()vs. $this->myMethod())是您没有考虑当班级是其父母的大孩子时会发生什么,例如......

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();
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,即使你打算采用父亲的方法,他们也会给你孩子的方法.如果你从不打算在扩展类中覆盖它,只需将方法声明为final,并且从对象上下文调用$ this-> myMethod()时应该总是正常.