很多面试官在面试的时候都会问一些面向对象的问题,面向对象的三大特性中,多态最主要的实现方式就是方法的重载和重写 。但是在php中,只有重写,并没有完全的重载能力的实现 。
重写,子类重写父类方法 。
// 重写class A{ public function test($a) { echo 'This is A:' . $a, PHP_EOL; }}class childA extends A{ public function test($a) { echo 'This is A child:' . $a, PHP_EOL; }}$ca = new childA();$ca->test(1);
这个在PHP中是没有任何问题的,子类可以重写父类的方法 。当实例化子类的时候,调用的就是子类实现的重写的方法 。
重载,相同方法名但参数数量或者类型不同 。
class A{ function foo($a){ echo $a; } // Fatal error: Cannot redeclare A::foo() function foo($a, $b){ echo $a+$b; }}
抱歉,这样写的结果将会是直接的报错 。PHP并不支持这样的重载能力 。而在PHP的官方手册上,重载的定义是使用__set()、__get()、__call()、__callStatic()等魔术方法来对无法访问的变量或方法进行重载 。这与我们所学习的面向对象中的重载完全不同,在手册中的note里也有很多人对此提出了疑问 。当然,我们今天并不会再去讲这些魔术方法的使用 。关于它们的使用可以参考我们之前写过的文章:PHP中的那些魔术方法(一)、PHP的那些魔术方法(二)
那么,在PHP中可以实现重载吗?当然可以,只不过会麻烦一些:
// 重载class B{ public function foo(...$args) { if (count($args) == 2) { $this->fooAdd(...$args); } else if (count($args) == 1) { echo $args[0], PHP_EOL; } else { echo 'other'; } } private function fooAdd($a, $b) { echo $a + $b, PHP_EOL; }}$b = new B();$b->foo(1);$b->foo(1, 2);
【PHP中的“重载”是个啥?】使用一个方法来调用其他方法,根据参数数量来进行判断,就可以实现参数数量不同的方法重载 。
// 使用__call()进行重载class C{ public function __call($name, $args) { if ($name == 'foo') { $funcIndex = count($args); if (method_exists($this, 'foo' . $funcIndex)) { return $this->{'foo' . $funcIndex}(...$args); } } } private function foo1($a) { echo $a, PHP_EOL; } private function foo2($a, $b) { echo $a + $b, PHP_EOL; } private function foo3($a, $b, $c) { echo $a + $b + $c, PHP_EOL; }}$c = new C();$c->foo(1);$c->foo(1, 2);$c->foo(1, 2, 3);
使用__call()魔术方法或许会更简单,但也会让一些新手在接手项目的时候蒙圈 。毕竟魔术方法对IDE是不友好的,这样的开发让__call()成为了一个模板方法,由它来定义操作的算法骨架 。我们也可以根据参数类型来模拟重载能力 。
推荐阅读
- 太极拳老年人不要“练” 零基础练太极拳的要领
- 比亚迪|一车碰两瓷!老头乐版“比亚迪海豚”亮相 车名让小鹏汽车无语
- 电动车|“变形金刚”是真的!林肯纯电概念车发布:擎天柱见了都想换
- 锻炼多长时间能减肥
- 跑步多少时间才能减肥
- 招聘|薪资过万招人也难?3大行业陷用工“瓶颈”!80后90后都去哪了?
- 水煮蛋|若将50cm“仙女管”塞入体内,最后会怎么样?答案和你想的一样吗
- 网友热议|女生晒成为“刘畊宏女孩”第3天 下楼双腿不受控:走姿让网友笑趴
- 蔬菜皇冠是指什么蔬菜?
- 金蝉子和如来佛祖是什么关系 金蝉子在佛教中的地位