深刻理解php“繼承“、“私有屬性“、“$this指向“的關係

像樹一樣活著發表於2020-11-04

在官方文件中指出,子類能繼承父類的 "公有屬性/方法"、"受保護的屬性/方法"
疑問1:父類的私有屬性會被繼承嗎?
疑問2:父類的私有屬性可以被覆蓋嗎?
疑問3:$this指向"private"屬性 與 $this 指向"public/protected"屬性的區別?

帶著上面三個問題,我們做以下的測試:

<?php

class father {

    public $a = 'f_1';

    protected $b = 'f_2';

    private $c = 'f_3';

    public function write_a(){
        echo $this->a;
        echo '<br/>';
    }

    public function write_b(){
        echo $this->b;
        echo '<br/>';
    }

    public function write_c(){
        echo $this->c;
        echo '<br/>';
    }
}



class son extends father {

    public $a = 's_1';

    protected $b = 's_2';

    private $c = 's_3';

    public function write_a(){
        parent::write_a();
        echo $this->a;
    }

    public function write_b(){
        parent::write_b();
        echo $this->b;
    }

    public function write_c(){
        parent::write_c();
        echo $this->c;
    }
}

$a = new son();

$a->write_a();       //輸出值  s_1  s_1
echo '<br/>';

$a->write_b();       //輸出值  s_2  s_2
echo '<br/>';

$a->write_c();       //輸出值  f_1  s_1

通過上面的例子我們可以看出,父類的私有屬性肯定是不會被覆蓋的,否則不同方法中,訪問的"$this->c"不會出現不同的值;

接上面的程式碼:

print_r($a)   

// 列印出來的值
// son Object ( [a] => s_1 [b:protected] => s_2 [c:son:private] => s_3 [c:father:private] => f_3 ) 

我們觀察到例項化類“son”後的物件"$a",發現“son”這個類也是繼承了"father"當中的"c"屬性,只不過在歸屬當中,區分了"son"中的"c"屬性與"father"中的“c”屬性。"son"無法使用"father"中的"c"屬性。

那為什麼執行

$a->write_c();       //輸出值  f_1  s_1


擷取上面的部分程式碼:

#class father 當中的程式碼:    
public function write_c(){
    echo $this->c;
    echo '<br/>';
}


#class son 當中的程式碼:
public function write_c(){
    parent::write_c();
    echo $this->c;
}        

輸出的值不同呢?

驗證1:在例項化"son"後的物件$a,"father"當中的"$this"與"son"當中的"$this"是否相同?

我們分別在對應方法中,輸出$this的值進行觀察:

擷取上面的部分程式碼:

#class father 當中的程式碼:    
public function write_c(){
    print_r($this); 
//  son Object ( [a] => s_1 [b:protected] => s_2 [c:son:private] => s_3 [c:father:private] => f_3 ) 
    echo $this->c;
    echo '<br/>';
}


#class son 當中的程式碼:
public function write_c(){
    print_r($this); 
//  son Object ( [a] => s_1 [b:protected] => s_2 [c:son:private] => s_3 [c:father:private] => f_3 )
    parent::write_c();
    echo $this->c;
}    

$this的值是相同的(都是例項化"son"類後的物件);

這時候我們可以明確,在$this指向上,對於"private"屬性與"public/protected"屬性肯定是不同的。

所以說我們可以這樣理解這個問題:

當例項化一個類產生物件時,如果類當中存在"私有屬性"(私有方法),並且在類的任意方法中,存在$this指向"私有屬性"(私有方法);此時$this指標始終指向的是$this所在類當中的"私有屬性"(私有方法),不會被子類中的同名屬性或者方法給覆蓋。同樣,子類中的"私有屬性"(私有方法),父類也不可能可以通過$this直接呼叫。

簡而言之,私有屬性(私有方法)僅僅屬於對其定義的類,無論該類處於繼承鏈的哪一個輩分當中。在類當中$this指向的“私有屬性”(私有方法)始終都是自己類當中定義的“私有屬性”(私有方法)。

 

 

相關文章