PHP中的子类访问受保护的方法 [英] Access protected method from child class in PHP

查看:101
本文介绍了PHP中的子类访问受保护的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以使用至少两种基本方法从子类访问 protected 类方法:

  parent :: myMethod(); 

$ this-> myMethod();

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

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

这是最常用的方法?我个人觉得使用 parent :: myMethod()而不是 $ this-> myMethod 更舒适,因为第一个立即告诉我这个方法是继承的。但我不知道在效果和最佳做法方面有哪些。



EDIT:



检查这,这是我的问题的真实情况。它使用CodeIgniter,但即使你不熟悉它,你可能会得到它:

  class Admin_Controller extends CI_Controller { 

protected function validate_form($ validation){
$ this-> load-> library('form_validation');
//这将验证根据$ validation中指定的验证规则组发送的表单
if($ this-> form_validation-> run($ validation)== false){
throw new Exception('在表单中有错误');
}
}

}

类文章extends Admin_Controller {

function save($ id){
$ this-> validate_form(strtolower(get_class($ this));
// OR
parent :: validate_form(strtolower(get_class($ this));
//其他操作
....
}

}

类登录扩展Admin_Controller {

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

}


的语义是这样的,它对它的父类进行转发调用。然而, $ this-> method()的语义是这样的,它只会将其调用转发给父类,被调用不声明该方法。同样重要的是要注意,一个孩子可能有一个父母以及一个父母,所以在设计原型时也必须仔细考虑。



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

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

这可确保任何扩展类将无法覆盖方法 。如果一个扩展类试图覆盖这个方法像下面的代码,你会得到一个致命错误致命错误:不能覆盖最后的方法MyClass :: myMethod()



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

此外,这会使您的代码更容易阅读,并且 / em>,因为你清楚地说明谁读取的代码,该方法是最终的,不能重写。



此外,你的方法的根本问题(如果你想使用 parent :: myMethod() $ 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(),\\\
; // Child :: myMethod
echo $ this-> myMethod(),\\\
; // Child :: myMethod
}
}

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

正如你可以看到,他们都会给你孩子的方法,即使你想要父亲的方法。只要声明该方法为final,如果你从来不打算在扩展类中重写它,你应该总是调用$ this-> myMethod()从对象上下文。


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

}

解决方案

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.

这篇关于PHP中的子类访问受保护的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆