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

问题描述 投票:3回答:4

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

parent::myMethod();

$this->myMethod();

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

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

最推荐的调用方式是?我个人使用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
            ....
    }

}
php codeigniter inheritance protected
4个回答
5
投票

他们做两件事。 parent关键字的语义使得它可以对其父类进行转发调用。但是,$this->method()的语义使得仅在调用该方法的实例未声明该方法的情况下,才将其调用转发给父类。还需要注意的是,孩子可能既有父母也有祖父母,因此在原型设计中也必须仔细考虑。

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

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

这将确保任何扩展类都不能覆盖该方法。如果扩展类尝试像下面的代码一样覆盖此方法,则会出现致命错误Fatal error: Cannot override final method MyClass::myMethod()

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

而且,这使您的代码更具可读性不太容易出错,因为您清楚地指出,凡是读取该代码的人都认为该方法是最终的并且不能被覆盖。

此外,您的方法的基本问题(如果您想使用parent::myMethod()$this->myMethod())是,您没有考虑到该类是其父级的[[grand child ,例如...

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();
您可以看到,即使您打算采用父亲的方法,他们也会给您孩子的方法。如果您不打算在扩展类中重写该方法,则只需将其声明为final方法即可,并且从对象上下文调用$ this-> myMethod()时应该总是可以的。

1
投票
据我了解,那是两件事。

$ this用于引用该类的实例,并且在创建对象后可用。因此,它将引用子类对象,而不是父类。

parent

是在子类中扩展父方法的正确方法。它引用父类,并具有额外的优点,即无需在许多级别上更改类名称。 self相似。请参见下面的两个实现示例。

    Accessing with parent keyword
  1. Accessing with this leads to unexpected behaviour.
  • 希望我能帮上忙。

  • 0
    投票
    当您调用parent :: method()时,它与$ this-> method()的方法不同。如果您在子类中覆盖它,则它可能返回不同的值

    0
    投票
    请参见下面的示例,该示例从子类中调用受保护的父方法。

    这样做的一个很好的理由是重用父级的功能,然后将其添加到子类中。

    class A{ protected $a; public function __construct(){ $this->setValueOfStringInA(); } protected function setValueOfStringInA(){ $this->a = "a set from A::setValueOfStringInA"; } public function getValueOfA(){ echo 'a of ' . __CLASS__ . ' = ' . $this->a . '<br>'; } } class B extends A{ protected $b; public function __construct(){ parent::__construct(); } protected function setValueOfStringInA(){ parent::setValueOfStringInA(); $this->b = "b set from B::setValueOfStringInA"; } public function getValueOfA(){ echo 'a of ' . __CLASS__ . ' = ' . $this->a . '<br>'; } public function getValueOfB(){ echo 'b of ' . __CLASS__ . ' = ' . $this->b . '<br>'; } } $objA = new A(); //the following call will not work since it is a protected method, it can not be called from outside, hence commented out. //$objA->setValueOfStringInA(); $objA->getValueOfA(); $objB = new B(); //$objB->setValueOfStringInA(); $objB->getValueOfB(); $objB->getValueOfA();

    检查输出:

    a of A = a set from A::setValueOfStringInA b of B = b set from B::setValueOfStringInA a of B = a set from A::setValueOfStringInA

    © www.soinside.com 2019 - 2024. All rights reserved.