PHP笔记:类和对象之重载和魔术方法

2018年10月7日22:37:30 发表评论 802 次
摘要

PHP所提供的”重载”(overloading)是指动态地”创建”类属性和方法,是通过魔术方法__set, __get,__isset, __unset实现的,从而分别实现对不可访问的(private或protected或不存在的)属性的赋值、读取、判断属性是否设置、销毁属性。在以下情形时会调用对应魔术方法。

PHP所提供的"重载"(overloading)是指动态地"创建"类属性和方法,是通过魔术方法__set, __get,__isset, __unset实现的,从而分别实现对不可访问的(private或protected或不存在的)属性的赋值、读取、判断属性是否设置、销毁属性。在以下情形时会调用对应魔术方法。

属性的重载

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

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

当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。

当对不可访问属性调用 unset() 时,__unset() 会被调用。

举个栗子:

class Car {
    private $data = [];
    //可访问属性不会重载
    public $price = 9999;
    //不可访问或不存在属性可重载
    private $speed = 299;
    public function __set($key, $val) {
        $this->data[$key] = $val;
    }
    public function __get($key) {
        if (isset($this->data[$key])) {
            return $this->data[$key];
        }
        return false;
    }
    public function __isset($key) {
        if (isset($this->data[$key])) {
            return true;
        }
        return false;
    }
    public function __unset($key) {
        unset($this->data[$key]);
        echo $key.'被销毁';
    }
}
$car = new Car();
$car->brand = 'Toyota';  //brand属性动态创建并赋值, 同时调用__set方法处理属性名及属性值
var_dump( $car->brand); //string(6) "Toyota", brand属性被重载,访问是调用__get魔术方法将数据取出
var_dump( $car->speed); //bool(false), 受保护属性不可访问,且未重载,__get方法返回false
var_dump( isset($car->brand)); //bool(true),brand被创建,调用__isset方法返回true。
var_dump( isset($car->speed)); //bool(false),brand不可访问属性,且未被创建,调用__isset方法返回false
unset($car->brand); //brand被销毁,调用__unset魔术方法。

注:魔术方法只是用来处理被重载的属性,即使不用魔术方法也可以创建属性;

方法的重载

方法的重载通过__call来实现,当调用不可访问的(private或protected或不存在)方法的时候,将会转为参数调用__call方法,当调用不可访问的(private或protected或不存在)静态方法时会使用__callStatic重载。

class Car {
    public static $speed = 150;  
    public function __call($name, $args) {
        if ($name == 'speedUp') {
            self::$speed += $args[0];
        }
    }   
    public static function __callStatic($name, $args) {
        if ($name == 'speedDown') {
            self::$speed -= $args[0];
        }
    } 
}
$car = new Car();
$car->speedUp(10); //调用不可访问的方法时__call被调用
echo Car::$speed,"\r\n";
Car::speedDown(99); \\在静态上下文中调用不可访问方法时,__callStatic被调用。
echo Car::$speed;

在__call和__callStatic中,$name 参数是要调用的方法名称。$arguments 参数是一个数组,包含着要传递给方法 $name 的参数。

avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: