extends
一個類可以在聲明中用extends關鍵字繼承另一個類的方法和屬性。PHP不支持多重繼承,一個類只能繼承一個基類。
被繼承的方法和屬性可以通過同樣的名字重新聲明被覆蓋,但是如果父類定義或者常量時是使用類final,則不可被覆蓋,可以通過parent::來訪問被覆蓋的方法或屬性。從PHP 8.1起,常量可以聲明為final。
final關鍵字:
final可用于類或方法:
- final類不能被繼承
- final方法不能被子類重寫
final class FinalClass { // 這個類不能被繼承final public function finalMethod() { // 這個方法不能被子類重寫// ...}
}
簽名兼容性規則
當覆蓋方法是,簽名必須兼容父類方法。否則會導致Fatal錯誤,PHP 8.0 前是 E_WARNING級錯誤。兼容簽名是指:遵守協變與逆變規則;強制參數可改為可選參數;添加的新參數只能是可選參數;放寬可見性而不是繼續限制。這就是里氏替換原則(LiskovSubstitution Principle)簡稱LSP。不過構造方法和私有(private)方法不需要遵循簽名兼容原則,就算簽名不匹配也不會造成Fatal錯誤。
子類與父類不兼容的例子:通過移除參數、修改可選參數為必填參數。
::class
關鍵詞class也可用于類名的解析。使用ClassName::class可獲取類ClassName的完全限定名稱。這對使用命名空間的類尤其有用。
自PHP 8.0起,::class 也可用于對象。此時解析將會在運行時進行。此操作的運行結果和在對象上調用get_class()相同。
Nullsafe方法和屬性
自PHP8.0起,類屬性和方法可通過“nullsafe”操作符訪問:?-> 。 除了一處不同,nullsafe操作符和以上原來的屬性、方法訪問是一致的:對象引用解析為null是不拋出異常,而是返回null。如果鏈式調用中的一部分,剩余鏈條會直接跳過。
屬性
類的變量成員叫做屬性,或者叫字段。屬性開頭至少用一個修飾符,除了readonly 屬性之外都是可選的,然后自PHP 7.4起可以跟一個類型聲明,然后跟一個普通的變量聲明來組成。屬性中的變量可以初始化,但初始化的值必須是常量值。
在類的成員方法里,可以用-> (對象運算符):$this->property (其中property是該屬性名)這種方式來訪問非靜態屬性。靜態屬性則是用::(雙冒號)self::$property 來訪問。更多靜態屬性與非靜態屬性的區別參見靜態static 關鍵字。
當一個方法在類定義內部被調用時,有一個可用的偽變量$this 。 $this是一個指向當前對象的引用。(通常是該方法所從屬的對象,但如果是另一個對象靜態調用,也可能是另一個)
類型聲明
從PHP 7.4起,屬性定義可以包含類型聲明,但callable除外
類型屬性必須在訪問前初始化,否則會拋出Error
只讀屬性
自PHP 8.1起,可用readonly修飾符聲明屬性,防止初始化后修改屬性。在PHP8.4前,readonly屬性是隱式的私有設置,只能從同一類寫入。從PHP 8.4 開始 , readonly屬性是隱式的protected(set) , 因此可從子類設置,若需要,可以顯式覆蓋。
只讀屬性只能初始化一次,并且只能從聲明它的作用域內初始化。對屬性的任何賦值和修改都會導致Error異常。
除了修改,以下操作也會導致Error異常:
只讀屬性不會妨礙內部可變性。存儲在只讀屬性中的對象(或資源)仍然可以在內部修改:
自PHP 8.3起,使用_clone()方法克隆對象時可以重新初始化readonly屬性
動態屬性
如果嘗試在object上賦值不存在的屬性,PHP將會自動創建相應的屬性。動態創建的屬性將僅能此類實例上使用。
由于PHP 8.2+不推薦動態屬性,可以使用:
class Flexible {private array $data = [];public function __set(string $name, mixed $value): void {$this->data[$name] = $value;}public function __get(string $name): mixed {return $this->data[$name] ?? null;}
}
參考資料
PHP手冊