问一个相互引用(或相互包含)的问题,为啥不起作用?

代码如下

class P{
    public $expr, $operand;
    function expr(){
        if(!isset($this->expr)){
            $this->expr = ['expr'];
            $this->expr[] = $this->operand();
        }
        return $this->expr;
    }
    function operand(){
        if(!isset($this->operand)){
            $this->operand = ['operand'];
            $this->operand[] = $this->expr();
        }
        return $this->operand;
    }
}

$o = new P;
print_r($o->expr());

$o->operand[] = 'operand2';
print_r($o->expr);

对象 o 的属性 expr 是一个数组,此数组含有一个元素 $o->operand;对象 o 的另一个属性 operand 也是一个数组,该数组反过来又包含元素 $o->expr。如此一来,对象 o 的两个属性形成“相互包含”或“相互引用”。

问题来了,给$o->operand添加一个元素 operand2 之后$o->expr上却看不到变化。可见这样写的相互引用是失败的,那正确的写法又是怎样的呢?

问一个相互引用(或相互包含)的问题,为啥不起作用?

执行结果如上图所示

讨论数量: 4

第一次访问方法后,就固定了两个变量的值,后面再怎么赋值也不会改变另一个变量的值了。
可以这样试下

$o->expr = null;
$o->operand[] = 'operand2';
print_r($o->expr());
1年前 评论
zhaiduting (楼主) 1年前
deatil (作者) 1年前

相互引用是可以实现的,将代码改了一下,不再使用 php 的原生数组,而是使用自定义的对象

class Arr{
    public $arr = [];
    function add($e){
        array_push($this->arr, $e);
        return $this;
    }
}

之后像下面这样修改 P 即可实现相互引用

class P{
    public $expr, $operand;
    function expr(){
        if(!isset($this->expr)){
            $this->expr = new Arr;
            $this->expr->add('expr')->add($this->operand());
        }
        return $this->expr;
    }
    function operand(){
        if(!isset($this->operand)){
            $this->operand = new Arr;
            $this->operand->add('operand')->add($this->expr());
        }
        return $this->operand;
    }
}

以下测试代码

$o = new P;
print_r($o->expr());

$o->operand->add('operand 2');
print_r($o->expr);

使用php沙箱测试可行,数据结构里面也出现了明显的 *RECURSION* 字样。难道非得自定义一个类才行?用原生数组怎么就不行了呢?

file

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!