PHP類中訪問控制的一些Tips

PHP類中訪問控制的一些Tips

包括PHP在內的大部分面向對象的編程語言,都提供了對類的變量或方法的訪問控制。這是實現面向對象封裝能力的基礎。變量其實就是數據,而方法函數就是處理這些數據的操做,根據最少知識原則,一些數據你不須要知道它的存在。這時,就須要使用private私有的變量和方法,私有的變量或方法只有這個類本身能夠訪問。而有些變量和方法本身的子類須要使用,但又不能暴露給外部,那麼咱們就會使用protected,也就是受保護的。最後就是公開無論類內部、外部仍是繼承的子類均可以使用的public公共變量或方法了。php

咱們經過變量的訪問控制先來複習一下這三種訪問控制符的做用。git

class A {
    private $private;
    protected $protected;
    public $public;

    public function setPrivate($p){
        $this->private = $p;
    }

    public function setProtected($p){
        $this->protected = $p;
    }

    public function setPublic($p){
        $this->public = $p;
    }

    public function testA(){
        echo $this->private, '===', $this->protected, '===', $this->public, PHP_EOL;
    }
}

class B extends A{
    public function testB(){
        echo $this->private, '===';
        echo $this->protected, '===', $this->public, PHP_EOL;
    }
}

$a = new A();
// $a->private = 'a-private'; // atal error: Uncaught Error: Cannot access private property A::$private 
$a->setPrivate('a-private');
// $a->protected = 'a-protected'; // atal error: Uncaught Error: Cannot access protected property A::$protected 
$a->setProtected('a-protected');
$a->public = 'c-public';
$a->testA();

echo "Out side public:" . $a->public, PHP_EOL;
// echo "Out side private:" . $a->private, PHP_EOL; // Fatal error: Uncaught Error: Cannot access private property A::$private
// echo "Out side protected:" . $a->protected, PHP_EOL; // Fatal error: Uncaught Error: Cannot access protected property A::$protected

$b = new B();
$b->setProtected('b-protected');
$b->public = 'b-public';
$b->testB(); // 沒有b-private

$b->setPrivate('b-private');
$b->testB(); // 沒有b-private

複製代碼

從上述代碼中很清晰的能夠看出,除了public以外的變量都不能在類外部直接調用或者賦值。因此咱們使用setXXX()的public方法來爲$private和$protected賦值。這裏就出現了封裝的概念了,好比在setPrivate()中咱們就能夠對傳遞過來的$p變量進行邏輯判斷而決定是否將值賦給$private。github


B類繼承了A類,因此它能夠訪問到A類的$public和$protected變量,可是,請注意,$private變量是沒法訪問到的。因此即便調用了setPrivate()方法爲$private賦值了,但由於B沒法訪問,因此依然取不到$private的值。有小夥伴要問了,這種狀況不報錯?固然不會報錯,B類會在本身的範圍內查找$private變量,沒有定義的話就會生成一個局部的變量並賦值爲空。編程


那麼子類要使用$private應該怎麼辦呢?bash

class C extends A {
    private $private;

    public function testC(){
        echo $this->private, '===', $this->protected, '===', $this->public, PHP_EOL;
    }

    // public function setPrivate($p){
    //     $this->private = $p;
    // }
}

$c = new C();
$c->setProtected('c-protected');
$c->public = 'c-public';
$c->setPrivate('c-private');
$c->testC();
複製代碼

先不要打開C類setPrivate()方法的註釋,你會發現$private依然是空值。也就是說,定義了同名的$private私有變量並非對父類的變量覆蓋,而是在本類做用域內新建了一個。父類的setPrivate()方法固然也不能訪問子類的private變量,所以,子類也要重寫一個setPrivate()方法來爲本身的$private變量賦值。微信


記住一點:private修飾的變量或方法僅對當前類開放
編程語言

對於方法的修飾也是同樣的效果。ide

class D {
    public function testD(){
        $this->show();
    }
    private function show(){
        echo 'This is D', PHP_EOL;
    }
}

class E extends D {
    private function show(){
        echo 'This is E', PHP_EOL;
    }
}

$e = new E();
$e->testD(); // This is D
複製代碼

子類E調用父類D的testD()方法,testD()方法中調用的是private修飾的show()方法,根據上面的原則,它依然調用的是本身D類的show()方法。函數

​總結

關於訪問控制的內容仍是比較簡單的,最主要的就是private這個修飾符的問題須要注意,其餘的其實仍是比較好理解的。不過越是簡單的東西越是基礎,面向對象脫離不了這三個簡單的訪問修飾符,它們在現代軟件開發中的分量十足,只有緊緊掌握它們纔是咱們正確的學習之道。oop

測試代碼:github.com/zhangyue050…

參考文檔:www.php.net/manual/zh/l…www.php.net/manual/zh/l…www.php.net/manual/zh/l…


===============

關注公衆號:【硬核項目經理】獲取最新文章

添加微信/QQ好友:【DarkMatterZyCoder/149844827】免費得PHP、項目管理學習資料
相關文章
相關標籤/搜索