PHP所提供的”重载”(overloading)是指动态地”创建”类属性和方法。我们是通过魔术方法(magic methods)来实现的。当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。本节后面将使用”不可访问属性”和”不可访问方法”来称呼这些未定义或不可见的类属性或方法。所有的重载方法都必须被声明为 public。
class Parent1 {
public function printFunction ($args) {
echo 'parent1->printfunction ' . $args . '
';
}
public function printFunction1 ($args) {
echo 'parent1->printfunction1 ' . $args . '
';
}
}
class Parent2 {
public function printFunction2 ($args) {
echo 'parent2->printfunction2 ' . $args . '
';
}
}
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 . '
';
}
}
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的具体实现。