php 魔术方法 多继承,PHP通过魔术方法实现多继承与重载

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的具体实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值