包括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
參考文檔:www.php.net/manual/zh/l…www.php.net/manual/zh/l…www.php.net/manual/zh/l…