php面向对象之重载(overloading)

在java中,重载就是函数或者方法有相同的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法,这也牵涉到了多态。

在PHP中呢,有人说php没有多态,那重载呢?

PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法,分为属性的重载和方法的重载;

我们是通过魔术方法(magic methods)来实现的,当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。本节后面将使用"不可访问属性(inaccessible properties)"和"不可访问方法(inaccessible methods)"来称呼这些未定义或不可见的类属性或方法。

属性重载

public void __set ( string $name , mixed $value )
public mixed __get ( string $name )
public bool __isset ( string $name )
public void __unset ( string $name )

在给不可访问的属性赋值时,__set() 会被调用。

读取不可访问的属性的值时,__get()会被调用。

当判断不可访问的属性是否存在的时候(使用isset(),empty())时,__isset()会被调用。

当对不可访问的属性执行销毁操作(unset())的时候,__unset()会被调用。

__get()方法,有两个参数,$name是指要操作的变量名称(另外三个都是这个意思),$value是指对应name的值。

一个很简单的例子:

class Person {
    public $name;
    private $age;

    public function __set($name, $value)
    {
        echo "你赋值的属性{$name}不存在";
    }

    public function __get($name)
    {
        echo "你所访问的属性{$name}不存在";
    }

    public function __isset($name)
    {
        echo "你判断的属性{$name}不存在";
    }

    public function __unset($name)
    {
        echo "你销毁的属性{$name}不存在";
    }
}

$person = new Person();
echo '赋值操作:',$person->gender = 'nale',<br />';
echo '取值操作:',$person->gender,'<br />';
echo 'isset判断操作:',isset($person->gender),'<br />';
echo 'empty判断操作:',empty($person->gender),'<br />';
echo 'empty判断操作:',empty($person->gender),'<br />';
echo 'unset操作:';unset($person->gender);
结果如下:


empty这里后面有个1是因为当前返回的是true,输出来就是1了;

当然,大家也会发现,没有这些魔术方法,我照样可以跑通,我把这些魔术方法注释掉:

class Person {
    public $name;
    private $age;

//    public function __set($name, $value)
//    {
//        echo "你赋值的属性{$name}不存在";
//    }
//
//    public function __get($name)
//    {
//        echo "你所访问的属性{$name}不存在";
//    }
//
//    public function __isset($name)
//    {
//        echo "你判断的属性{$name}不存在";
//    }
//
//    public function __unset($name)
//    {
//        echo "你销毁的属性{$name}不存在";
//    }
//
//    public function __call($name, $arguments)
//    {
//        echo '你在调用不存在的方法';
//    }
}

$person = new Person();
echo '赋值操作:',$person->gender = 123,'<br />';
echo '取值操作:',$person->gender,'<br />';
echo 'isset判断操作:',isset($person->gender),'<br />';
echo 'empty判断操作:',empty($person->gender),'<br />';
echo 'empty判断操作:',empty($person->gender),'<br />';
echo 'unset操作:';unset($person->gender);
echo '取值操作:',$person->gender,'<br />'; //访问不存在的属性,因为被销毁了,应该会报一个notic级别的错误

运行如下所示:


这个是因为在PHP中,并没有强制属性都在类中声明,这是动态的给对象属性赋值,在其它强类型语言中,可能行不通,所以在一般时候,并不建议这样写。

那如果有这种动态增加值的需求的时候怎么办呢,我们可以利用属性的重载来完成,如下:

class Person {
    public $name;
    private $age;
    private $_attr = array();

    public function __construct($name,$age)
    {
        $this->name = $name;
        $this->age = $age;
    }

    public function __get($name)
    {
        if($this->_attr[$name]){
            return $this->_attr[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        $this->_attr[$name] = $value;
    }

    public function __isset($name)
    {
        return isset($this->_attr[$name]);
    }
    public function __unset($name)
    {
        unset($this->_attr[$name]);
    }
}

$person = new Person('lightWay', 24);

//赋值操作
$person->gender = 'male';
$person->home = 'hubei';

echo $person->home; //取值操作
unset($person->home); //销毁操作

方法重载

public mixed __call ( string $name , array $arguments )
public static mixed __callStatic ( string $name , array $arguments )

在对象中调用一个不可访问方法时,__call() 会被调用。


在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用。

$name 参数是要调用的方法名称。$arguments 参数是一个枚举数组,包含着要传递给方法 $name 的参数。

上代码说明吧:

class Person {
    public function __call($name, $arguments)
    {
        echo '您正在调用一个不存在的方法',self::class,'::',$name,PHP_EOL;
        print_r($arguments);
    }

    public static function __callStatic($name, $arguments)
    {
        echo '您正在调用一个不存在的静态方法',self::class,'::',$name,PHP_EOL;
        print_r($arguments);
    }
}

$person = new Person();
$person->sayMyInfo1('123',2,true);
$person::show(1,2,3);
执行结果如下:



我们可以用PHP中的重载,去模拟其他语言中的重载,代码如下:

class Person {
    public $name;
    public function __construct($name)
    {
        $this->name = $name;
    }

    public function __call($name, $arguments)
    {
        if($name == 'eating') {
            switch (count($arguments)) {
                case 1 :
                    echo "{$this->name}正在用{$arguments[0]}吃中餐",PHP_EOL;
                    break;
                case 2 :
                    echo "{$this->name}正在用{$arguments[0]}和{$arguments[1]}吃西餐",PHP_EOL;
                    break;
                case 0:
                default:
                    echo "{$this->name}在喝西北风",PHP_EOL;
                    break;
            }
        } else {
            echo '您访问的方法不存在';
        }
    }


}

$my = new Person('lightWay');

$my->eating('筷子');

$my->eating('刀','叉子');

$my->eating();

执行结果如下:


这里只是用了参数的不同,来执行不同的动作,可以利用的点很多,很多框架都会到这个,好吧,这里就完了,看完了,你还觉得PHP没用多态吗?

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值