在 PHP 中,類的繼承(繼承)是一種機制,允許一個類繼承另一個類的屬性和方法,從而實現代碼的重用和擴展。繼承可以幫助你創建一個基于現有類的新類,保留原有類的特性并增加或修改其功能。
class Animal { public $name='dongwu'; protected $age=1; private $birth='2024'; } class Cat extends Animal{} //使用extends 關鍵字繼承父類 注意花括號后面沒有分號 var_dump(new Animal); var_dump(new Cat);
var_dump 2個類看看內容,除了名字不同,內容都是一樣的。
[Running] D:\ceshi.test\3.php"
object(Animal)#1 (3) {
["name"]=>
string(6) "dongwu"
["age":protected]=>
int(1)
["birth":"Animal":private]=>
string(4) "2024"
}
object(Cat)#1 (3) {
["name"]=>
string(6) "dongwu"
["age":protected]=>
int(1)
["birth":"Animal":private]=>
string(4) "2024"
}
接下來嘗試調用Animal類的變量
class Animal { public $name='dongwu'; protected $age=1; private $birth='2024'; } class Cat extends Animal{} $obj = new Cat; echo $obj->name; //只有這個public 的name可以被打印 echo $obj->age; //雖然是子類可以拿到,但是是在類的內部可以拿到,外部想要拿到的話,需要使用函數的方式拿到 echo $obj->birth; //私有類型的,子類無法拿到
接下來演示如何拿到protected的age
class Animal { public $name='dongwu'; protected $age=1; private $birth='2024'; } class Cat extends Animal{ function getage(){ //使用方法拿到age,由此可見protected類型的變量只能在類的內部拿到 echo $this->age; } } $obj = new Cat; echo $obj->getage();
回顯如下:
[Running] D:\ceshi.test\3.php"
1
接下來再看下面的這段代碼
class Animal { protected $name; public function __construct($name){ $this->name =$name; //通過構造函數賦值給類里面的name變量 } public function eat(){ echo $this->name. ' is eatting'; } } class Cat extends Animal{ public function meow(){ //子類自有的方法 echo $this->name.'is meowing'; } } $cat = new Cat('lanmao'); var_dump($cat); $cat->eat(); $cat->meow();
回顯如下:
[Running] D:\ceshi.test\3.php"
object(Cat)#1 (1) {
["name":protected]=>
string(6) "lanmao"
}
lanmao is eattinglanmaois meowing
由此可見 vardump只能打印出父類的變量(屬性),而不能打印出方法。實際是可以繼承過來的,只是無法通過vardump打印出來。比如父類的構造方法和其他方法都被繼承了過來。
類方法和屬性(變量)的重寫
如果從父類繼承的方法或屬性不能滿足子類的需求,可以對其進行改寫,下面的這段代碼中父類雖然有了eat方法,但是子類在繼承后又重寫了eat方法,所以會執行子類的eat方法而忽略父類的eat方法
class Animal { protected $name; public function __construct($name){ $this->name =$name; } public function eat(){ echo $this->name. ' is eatting'; //雖然父類中有了eat方法 } } class Cat extends Animal{ public function eat(){ echo $this->name. ' is eatting2'; //子類重寫了eat方法后,會忽略父類中的eat方法 } public function meow(){ echo $this->name.'is meowing'; } } $cat = new Cat('lanmao'); $cat->eat();
回顯如下:
[Running] D:\ceshi.test\3.php"
lanmao is eatting2
同樣,屬性(變量)也可以重寫,看下面的例子
class Animal { protected $name='fish'; //初始值設置為fish public function eat(){ echo $this->name. ' is eatting'; } } class Cat extends Animal{ protected $name='fox'; //子類中重寫屬性 public function meow(){ echo $this->name.' is meowing'; } } $cat = new Cat(); $cat->meow();
回顯如下:
[Running] D:\ceshi.test\3.php"
foxis meowing
final 關鍵字
作用:
防止類被集成
防止類的方法被重寫
先看阻止類方法重寫
class Animal { protected $name; public function __construct($name){ $this->name =$name; } final public function eat(){ //類方法前加上final,則這個類無法被繼承 echo $this->name. ' is eatting'; } } class Cat extends Animal{ public function eat(){ echo $this->name. ' is eatting2'; } public function meow(){ echo $this->name.'is meowing'; } } $cat = new Cat('lanmao');$cat->eat();
回顯如下:
[Running] D:\ceshi.test\3.php
PHP Fatal error: Cannot override final method Animal::eat() in D:\phpstudy_pro\WWW\ceshi.test\3.php on line 30
Fatal error: Cannot override final method Animal::eat() in D:\phpstudy_pro\WWW\ceshi.test\3.php on line 30
再看阻止類繼承
final class Animal { //此處加上final來阻止類被繼承 protected $name; public function __construct($name){ $this->name =$name; } public function eat(){ echo $this->name. ' is eatting'; } } class Cat extends Animal{ public function eat(){ echo $this->name. ' is eatting2'; } public function meow(){ echo $this->name.'is meowing'; } } $cat = new Cat('lanmao');$cat->eat();
回顯如下:
[Running] D:\ceshi.test\3.php"
PHP Fatal error: Class Cat may not inherit from final class (Animal) in D:\phpstudy_pro\WWW\ceshi.test\3.php on line 30
Fatal error: Class Cat may not inherit from final class (Animal) in D:\phpstudy_pro\WWW\ceshi.test\3.php on line 30
在 PHP 中,可以通過
parent:: 關鍵字在子類中調用父類的方法。例如:class ParentClass { public function greet() { echo "Hello from ParentClass!"; } } class ChildClass extends ParentClass { public function greet() { // 調用父類的 greet() 方法 parent::greet(); echo " And hello from ChildClass!"; } } $child = new ChildClass(); $child->greet();
回顯如下:
[Running] D:\ceshi.test\6.php"
Hello from ParentClass! And hello from ChildClass!
繼續看調用父類的構造函數
class ParentClass { public function __construct($name) { echo "ParentClass constructor with name: $name"; //父類的構造函數有一個name傳進來 } } class ChildClass extends ParentClass { public function __construct($name, $age) { // 調用父類的構造函數 parent::__construct($name); echo "ChildClass constructor with age: $age"; //不僅能輸出自己的構造函數,還能輸出父類的構造函數 } } $child = new ChildClass('Alice', 25);
回顯如下:
[Running] D:\ceshi.test\6.php"
ParentClass constructor with name: Alice
ChildClass constructor with age: 25
同樣,也可以重寫父類繼承過來的構造函數
class ParentClass { public function __construct($name) { echo "ParentClass constructor with name: $name"; } } class ChildClass extends ParentClass { public function __construct($age) { // 直接重寫繼承自父類的構造函數,需要注意的是父類的構造函數本身不會受到影響 echo "ChildClass constructor with age: $age"; } }
回顯如下:
[Running] D:\ceshi.test\6.php"
ChildClass constructor with age: 25
靜態延遲綁定static
是指在運行時根據實際調用的類來確定靜態方法或屬性的綁定
static::$name
來看下面這段代碼
在這個示例中,
self::$name 和 static::$name 的行為是不同的。self::$name 在任何情況下都指向 Animal 類的 $name 屬性,而 static::$name 使用的是靜態延遲綁定,這意味著它會指向當前調用 eat() 方法的類的 $name 屬性。由于你是通過 Animal::eat() 調用的,結果如下:<?php class Animal { protected static $name = 'Animal'; public static function eat() { echo self::$name . ' is eating'; echo '----'; echo static::$name . ' is eating'; } } Animal::eat(); ?>
[Running] D:\ceshi.test\6.php"
Animal is eating----Animal is eating
如果你有子類
Dog 繼承自 Animal,并重寫 $name 屬性,調用 Dog::eat() 將會展示不同的結果:<?php class Animal { protected static $name = 'Animal'; public static function eat() { echo self::$name . ' is eating'; echo '----'; echo static::$name . ' is eating'; } } class Dog extends Animal { protected static $name = 'Dog'; } Dog::eat(); ?>
[Running] D:\phpstudy_pro\Extensions\php\php7.3.4nts\php.exe "d:\phpstudy_pro\WWW\ceshi.test\6.php"
Animal is eating----Dog is eating
此時
static::$name 使用靜態延遲綁定,指向實際調用方法的類 Dog 中的 $name 屬性。由于 Dog 類覆蓋了 Animal 類的 $name 屬性,所以 static::$name 輸出的是 Dog.這就是靜態綁定
浙公網安備 33010602011771號