如何在扩展类中从父对象中删除属性?

3
我试图在一个我无法修改的类中写一个变量的“监听器”。我扩展了所涉及的类,取消了我想要监听的属性,然后使用__set来拦截对该变量的写入。此时,我会将其与先前版本进行比较,并报告是否有更改。
class A {
    var $variable;

    ...
}

class B extends A {
    var $new_variable

    function __construct() {
        parent::__construct();
        unset($this->variable);
    }

    function __set($thing, $data) {
        if ($thing == 'variable') {
            // Report change
            // Set $new_variable so we can use __get on it
        }
    }

    public function __get($var) {
        if (isset($this->$var)) {
            // Get as normal.
            return $this->$var;
        } elseif ($var == 'variable' && isset($this->new_variable)) {
            return $this->new_variable;
        }
    }

    ...
}

如果我直接修改相关类而不是通过扩展类来进行修改,即删除变量的声明并引入setter和getter方法,则此方法有效。问题在于当我使用上面所示的模式时,unset()调用似乎并没有实际删除从父类继承的变量,因此使得__set方法无法拦截变量的值。
到目前为止,这似乎是我能够观察变量更改的唯一方法,但我不想黑客攻击框架的核心,只是检查它的便利工具(解析器)的工作。有没有可能使这个工作,或者另一种方法来解决这个问题?

事实证明,问题的一部分原因是我在__get方法中使用property_exists()而不是isset()来检查属性是否存在。 - epocsquadron
1个回答

2

嗯,这很奇怪。以下代码运行正常:

class A 
{
    var $variable;
}

class B extends A 
{
    var $new_variable;

    function __construct() 
    {
        unset($this->variable);
    }

    function __set($thing, $data) 
    {
        if ($thing == 'variable') 
        {
        echo "\nThe variable value is '" . $data . "'\n";
        }
    }
}

$b = new B();
$b->variable = 'Intercepted'; //Output: The variable value is 'Intercepted'
$b->new_variable = 'Not intercepted'; // No output

您能告诉我这段代码是否符合您的需求,如果不是,您需要什么?

希望对您有所帮助


这个例子对我确实有效,但是当我特别应用到我的代码库时却不行。我已经慢慢地添加了逻辑,几乎到了与原来相同的代码点。测试例子可以运行,而真正的代码却不能。我仍在调查可能有何不同之处。 - epocsquadron
我已经追踪到问题所在,我的过载类被替换为父类的实例。看起来一直都是这样工作的。我接受你的答案,认为它没有任何问题。 :) - epocsquadron
好的,谢谢。虽然我没有提供太多帮助,但我很高兴你找到了问题 :) - Andrés Fortier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接