• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

PHP中的重载是个啥

php 搞代码 3年前 (2022-02-28) 34次浏览 已收录 0个评论

很多面试官在面试的时候都会问一些面向对象的问题,面向对象的三大个性中,多态最次要的实现形式就是办法的重载和重写。然而在PHP中,只有重写,并没有齐全的重载能力的实现。

重写,子类重写父类办法。

<code class="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中是没有任何问题的,子类能够重写父类的办法。当实例化子类的时候,调用的就是子类实现的重写的办法。

重载,雷同办法名但参数数量或者类型不同。

<code class="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中能够实现重载吗?当然能够,只不过会麻烦一些:

<code class="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);

应用一个办法来调用其余办法,依据参数数量来进行判断,就能够实现参数数量不同的办法重载。

<code class="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()成为了一个模板办法,由它来定义操作的算法骨架。咱们也能够依据参数类型来模仿重载能力。

<code class="php">// 参数类型不同的重载
class D {
    function __call($name, $args){
        if($name == 'foo'){
            if(is_string($args[0])){
                $this->fooString($args[0]);
            }else {
                $this->fooInt($args[0]);
            }
        }
    }
    private function fooInt(int $a){
        echo $a . ' is Int', PHP_EOL;
    }

    private function fooString(string $a){
        echo $a . ' is String', PHP_EOL;
    }
}

$d = new D();
$d->foo(1);
$d->foo('1');

不管怎么说,用上述办法实现的办法重载都十分麻烦,因为会让某一个办法或者魔术办法十分重,它须要成为一个控制器来依据参数对外部的办法进行调度。更多的状况下,咱们应该还是应用不同的办法名而后形象公共的局部提取成独立的公有外部办法来实现不同办法名的“重载”。毕竟不同的语言还是要把握它们不同的共性,并且依据这些共性灵便地使用在咱们的我的项目中。

测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/201912/source/PHP%E4%B8%AD%E7%9A%84%E2%80%9C%E9%87%8D%E8%BD%BD%E2%80%9D%E6%98%AF%E4%B8%AA%E5%95%A5%EF%BC%9F.php

参考文档:
https://www.php.net/manual/zh/language.oop5.overloading.php#77843

===========

各自媒体平台均可搜寻【硬核项目经理】


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:PHP中的重载是个啥

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址