在面向對象編程中,繼承是一個重要的概念。在PHP中,我們可以使用關鍵字extends來實現類繼承。不過在繼承中,一些方法或屬性可能并不想對外公開,這時我們可以使用protected關鍵字來限制其可見性。
假設我們有一個車輛類Vehicle,其中有一個公共屬性brand表示品牌。我們又創建了一個汽車類Car作為Vehicle的子類。為了將brand屬性保護起來,我們可以在Vehicle類的brand屬性前添加protected來實現:
class Vehicle { protected $brand; }
這時,在Vehicle類內部和其子類中,我們都可以訪問和修改這個屬性。但在Vehicle類的實例外部是無法訪問的:
class Car extends Vehicle { public function __construct() { $this->brand = 'BMW'; // 可以訪問 } } $car = new Car(); echo $car->brand; // 無法訪問
上述代碼中,我們創建了一個Car實例并嘗試訪問其brand屬性,但因為其被定義為protected,所以在實例外部無法訪問。
另外需要注意的是,在子類中訪問在父類中被定義為protected的屬性或方法時,需要使用parent關鍵字來調用:
class Car extends Vehicle { public function setBrand($brand) { $this->brand = $brand; // 無法訪問 } public function setParentBrand($brand) { parent::$brand = $brand; // 可以訪問 } }
上述代碼中,在setBrand方法中,我們嘗試直接訪問Vehicle類中的brand屬性,但由于其可見性被限制為protected,所以我們無法直接訪問。但在setParentBrand方法中,我們使用了parent關鍵字來訪問Vehicle類中的屬性,這樣就可以成功地修改其值了。
使用protected來保護方法時,其用法和屬性是類似的。我們只需要將方法的可見性設置為protected,即可在子類中訪問和重寫:
class Vehicle { protected function drive() { echo 'I am driving'; } } class Car extends Vehicle { public function drive() { parent::drive(); echo ' a car.'; } } $car = new Car(); $car->drive(); // 輸出 “I am driving a car.”
上述代碼中,我們在Vehicle類中定義了一個drive方法,并將其可見性設置為protected。在子類Car中,我們重寫了這個方法,并通過parent::drive()調用了父類中的方法。這樣就可以在子類中完全控制父類的方法邏輯了。
總而言之,通過使用protected關鍵字,我們可以在子類中訪問和重寫父類中被保護起來的屬性和方法。這種特性可以幫助我們更好地控制類成員的可見性,同時也保證了類的封裝性和安全性。