PHP所提供的”重载”(overloading)是指动态地”创建”类属性和方法。我们是通过魔术方法(magic methods)来实现的。当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。本节后面将使用”不可访问属性”和”不可访问方法”来称呼这些未定义或不可见的类属性或方法。所有的重载方法都必须被声明为 public。
<?php class Parent1 { public function printFunction ($args) { echo 'parent1->printfunction ' . $args . '<br>'; } public function printFunction1 ($args) { echo 'parent1->printfunction1 ' . $args . '<br>'; } } class Parent2 { public function printFunction2 ($args) { echo 'parent2->printfunction2 ' . $args . '<br>'; } } class Child { protected $_parents = null; public function __construct($parents) { $this->_parents = $parents; } public function __call($method, $args) { foreach ($this->_parents as $p) { if (is_callable(array($p, $method))) { return call_user_func_array(array($p, $method), $args); } } } public function printFunction ($args) { echo 'child->printfunction ' . $args . '<br>'; } } class A { protected $_parents = null; public function __construct($parents) { $this->_parents = $parents; } public function __call($method, $args) { foreach ($this->_parents as $p) { if (is_callable(array($p, $method))) { return call_user_func_array(array($p, $method), $args); } } } } class B extends Child{ public function __construct($parent){ parent::__construct($parent); } } $obj = new Child(array(new Parent1(), new Parent2())); $a = new A(array(new Child(array(new Parent1(), new Parent2())))); $b = new B(array(new Parent1(), new Parent2())); $obj->printFunction(123); // child->printfunction 123 $obj->printFunction1(456); // parent1->printfunction1 456 $obj->printFunction2(789); // arent2->printfunction2 789 $a->printFunction(123); // child->printfunction 123 $a->printFunction1(456); // parent1->printfunction1 456 $a->printFunction2(789); // arent2->printfunction2 789 $b->printFunction(123); // child->printfunction 123 $b->printFunction1(456); // parent1->printfunction1 456 $b->printFunction2(789); // arent2->printfunction2 789
当执行$obj->printFunction(123)时,由于在Child类中定义了此方法,所以直接调用Child中的printFunction方法。而执行$obj->printFunction1(456)和$obj->printFunction2(789)时,由于Child类中未定义printFunction1和printFunction2方法,就会自动调用__call方法,该方法的第一个参数是调用的不存在的方法的名称,是字符串类型,第二个参数是要传递的参数,是数组类型。在__call方法中查找引用的类的实例中是否存在该方法。类A和类B分别为实现不同的“继承”方法,他们的结果是一样的。用静态方式中调用一个不可访问方法时,__callStatic() 会被调用。
对于属性的重载也是同样的道理。
在给不可访问属性赋值时,__set() 会被调用。
读取不可访问属性的值时,__get() 会被调用。
当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。
当对不可访问属性调用 unset() 时,__unset() 会被调用。
还请读者参照PHP文档进行具体实现,若要了解详细使用,可参考yii中yii\base\Object的property和yii\base\Component的behavior的具体实现。