簡體   English   中英

從 PHP 中的子類訪問受保護的方法

[英]Access protected method from child class in PHP

我至少可以使用兩種基本方法從子類訪問受保護的類方法:

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

}

他們做兩件不同的事情。 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() 是你沒有考慮當類是它的孫子時會發生什么父母,例如...

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() 時應該總是沒問題的。

據我了解,這是兩個不同的東西。

$this用於引用類的實例,並且在創建對象后可用。 因此它將引用子類對象,而不是父類。

parent是在子類中擴展父方法的正確方法。 它指的是父類,並且有一個額外的好處,即類名的更改不需要在許多級別上完成。 自我是相似的。

有關示例,請參見下面的兩個實現。

  1. 使用 parent 關鍵字訪問
  2. 使用此訪問會導致意外行為。

希望我能幫上忙。

當您調用 parent::method() 時,它是不同於 $this->method() 的方法。 如果您在子類中覆蓋它,它可能會返回不同的值

有關從子類調用受保護的父方法的示例,請參見下文。

這樣做的一個很好的理由是重用父類的功能,然后在子類中添加該功能。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM