PHP类方法重写原则
可能我们日常工作中很少用到这块知识点,但我还是喜欢把遇到的却不清楚的知识点摸清
PHP的类方法重写规则
1、final修饰的类方法不可被子类重写
final修饰的类方法不可被子类重写 即便final private方法无法被继承 子类仍不能对齐进行重写
1 class FinalMethod 2 { 3 //可继承不可重写 4 final public function finalPublic() 5 { 6 echo "can be inherited, but be overrided"; 7 } 8 //可继承不可重写 9 final protected function finalProtected() 10 { 11 echo "can be inherited, but be overrided"; 12 } 13 //不可继承不可重写 虽然子类继承不到父类的private方法 但同时也会被final限制无法重写 14 final private function finalPrivate() 15 { 16 echo "can not be inherited or be overrided"; 17 } 18 //虽然不可继承 但子类里可重写此方法 19 private function private() 20 { 21 echo "can not be inherited ,but be overrided"; 22 } 23 } 24 25 class Override extends FinalMethod 26 { 27 //error 28 public function finalPublic() 29 { 30 } 31 //error 32 protected function finalProtected() 33 { 34 } 35 //error 36 private function finalPrivate() 37 { 38 } 39 //correct 40 public/protected/private function private() 41 { 42 //子类继承父类重写父类方法时访问级别只能更加宽松 不可更为严格 43 } 44 }
2、PHP是否重写父类方法只会根据方法名是否一致判断(5.3以后重写父类方法参数个数必须一致)
这里并不是说方法参数无任何作用 PHP无重载机制 所以判断是不是重写只会通过方法名(C/C++不仅要方法名相同,参数也相同时才被视为重写,否则即为重载,即新定义了一个多态函数的态) 当方法名相同时即被认为是在重写父类方法,5.2可以参数不同,5.3以后参数需和父类方法一致,且都追寻继承访问级别的规则。
1 class Father 2 { 3 public function index($args_1) 4 { 5 } 6 } 7 8 class Child extends Father 9 { 10 //5.3以后重写方法必须与父类保持参数个数相同 11 public function index($args_1, $args_2) 12 { 13 //在C/C++中此为重载非重写,因为C/C++具有标准的多态机制,会因参数不同而视为某一方法的另一种态 14 //but在php中此依然为重写 但5.3以后此为非法 必须与父类的方法参数个数保持一致 15 } 16 //5.3以后重写方法必须与父类保持参数个数相同 17 private function index($args_1, $args_2) 18 { 19 //C/C++会因为参数不同于父类方法而视为重载,即新定义了一个函数的态,所以不会受到继承访问权限的限制 20 //但php仍然会被视为对父类方法的重写,会受到继承访问权限的升降规则限制 21 } 22 }
3、重写时访问级别只可以等于或者宽松于父类 不可提升访问级别
父类的public方法不能被子类重写为protected或者private,protected方法不能被重写为private,可以宽松er,不可以严格er
1 class Father 2 { 3 public function index() 4 { 5 } 6 } 7 8 class Child extends Father 9 { 10 protected/private function index() 11 { 12 //访问权限提升 错误 13 //父类为public 则子类重写也只能为public 14 //父类为protected 则子类可为public/protected 15 //父类为private 则子类public/protected/private皆可 16 } 17 }
其实关于访问级别继承规则有很多有趣的地方
private在我们常识中是无法被继承的,子类拿不到,但其访问级别已是最高,所以你在子类中可以写成private protected public 仿佛是我们自己重新定义了一个函数一样,这点在5.2版本之前尤其突出,因为5.2之前的版本在继承重写父类方法是可以不保持参数个数相同,但5.3以后加强了这方面的限制,参数个数必须与父类相同
注:
子类实现父类的抽象方法或某类实现接口的方法时其实仍属于继承关系,仍追寻访问等级只能降低不可提升的规则
而且
抽象方法不可被声明为private,abstract修饰的方法肯定是用于继承实现的,所以只能是public或者protected 接口的方法声明必须为public,interface里声明的方法也肯定是被继承实现的,且只能是public, implements 此接口的类也指定重写成public类型的方法