php面向对象之重载(overloading)

来源:互联网 发布:用java做一个登录界面 编辑:程序博客网 时间:2024/05/17 23:05

在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没用多态吗?

0 0