可能我們日常工作中很少用到這塊知識點,但我還是喜歡把遇到的卻不清楚的知識點摸清
PHP的類方法重寫規則
1、final修飾的類別方法不可被子類別重寫
final修飾的類別方法不可被子類別重寫 即便final private方法無法被繼承 子類別仍不能對齊進行重寫
class FinalMethod { //可继承不可重写 final public function finalPublic() { echo "can be inherited, but be overrided"; } //可继承不可重写 final protected function finalProtected() { echo "can be inherited, but be overrided"; } //不可继承不可重写 虽然子类继承不到父类的private方法 但同时也会被final限制无法重写 final private function finalPrivate() { echo "can not be inherited or be overrided"; } //虽然不可继承 但子类里可重写此方法 private function private() { echo "can not be inherited ,but be overrided"; } } class Override extends FinalMethod { //error public function finalPublic() { } //error protected function finalProtected() { } //error private function finalPrivate() { } //correct public/protected/private function private() { //子类继承父类重写父类方法时访问级别只能更加宽松 不可更为严格 } }
2、PHP是否重寫父類別方法只會根據方法名是否一致判斷(5.3以後重寫父類方法參數個數必須一致)
這裡並不是說方法參數無任何作用PHP無重載機制所以判斷是不是重寫只會通過方法名(C/C++不僅要方法名相同,參數也相同時才被視為重寫,否則即為重載,即新定義了一個多態函數的態) 當方法名相同時即被認為是在重寫父類別方法,5.2可以參數不同,5.3以後參數需和父類別方法一致,且都追尋繼承存取等級的規則。
class Father { public function index($args_1) { } } class Child extends Father { //5.3以后重写方法必须与父类保持参数个数相同 public function index($args_1, $args_2) { //在C/C++中此为重载非重写,因为C/C++具有标准的多态机制,会因参数不同而视为某一方法的另一种态 //but在php中此依然为重写 但5.3以后此为非法 必须与父类的方法参数个数保持一致 } //5.3以后重写方法必须与父类保持参数个数相同 private function index($args_1, $args_2) { //C/C++会因为参数不同于父类方法而视为重载,即新定义了一个函数的态,所以不会受到继承访问权限的限制 //但php仍然会被视为对父类方法的重写,会受到继承访问权限的升降规则限制 } }
3、重寫時存取等級只可以等於或寬鬆於父類別不可提升存取等級
父類別的public方法不能被子類別重寫為protected或private,protected方法不能被重寫為private,可以寬鬆er,不可以嚴格er
class Father { public function index() { } } class Child extends Father { protected/private function index() { //访问权限提升 错误 //父类为public 则子类重写也只能为public //父类为protected 则子类可为public/protected //父类为private 则子类public/protected/private皆可 } }
其實關於訪問級別繼承規則有很多有趣的地方
private在我們常識中是無法被繼承的,子類拿不到,但其訪問級別已是最高,所以你在子類別中可以寫成private protected public 彷彿是我們自己重新定義了一個函數一樣,這點在5.2版本之前尤其突出,因為5.2之前的版本在繼承重寫父類別方法是可以不保持參數個數相同,但5.3以後加強了這方面的限制,參數個數必須與父類相同
註:
子類實現父類的抽象方法或某類實現接口的方法時其實仍屬於繼承關係,仍追尋訪問等級只能降低不可提升的規則, 而且抽象方法不可被宣告為private,abstract修飾的方法肯定是用於繼承實作的,所以只能是public或protected 介面的方法宣告必須為public,interface裡宣告的方法也肯定是被繼承實現的,而且只能是public, implements 此介面的類別也指定重寫成public類型的方法