【问题标题】:Prevent destructor from being called manually防止手动调用析构函数
【发布时间】:2014-01-15 12:41:46
【问题描述】:

我有这门课:

class Test
{
    private $test = 'ok';

    public function doTest()
    {
        echo $this->test;
    }

    public function __destruct()
    {
        $this->test = 'not ok';
    }
}

以及以下测试用例:

$test = new Test;
$test->__destruct(); // I wish this would throw a Fatal Error or something...
$test->doTest(); // prints "not ok"

我想要完成的是防止__destruct()被手动调用,这样doTest()就永远不会打印“not ok”。

我尝试将析构函数的可见性设置为private,但这只会导致对象销毁时出现致命错误。一个选项是在析构函数中设置一个标志$this->destructed,然后如果此标志为真,则在doTest() 中抛出一个异常,但每次调用该方法时检查此标志的效率不会很高。

所以,private 析构函数是不可能的,而标志 $this->destructed 是丑陋的。有更好的方法吗?

【问题讨论】:

  • 这是什么意思?为什么您的代码会手动调用对象的析构函数? - 如果发生这种情况,在我看来,那个应该是要解决的问题,而不是这个。
  • 我不完全清楚你想要完成什么。如果它是一个标志,无论该类是否已被破坏,您为什么要关心? PHP 垃圾收集对象并在对象失去作用域时调用其 __destruct() 方法
  • @Atli 我想确定,没有人会故意调用 __destruct()。如果对象在其析构函数被调用后仍然存在,它将破坏功能。
  • 你是什么,控制狂?如果有人真的想调用析构函数,那是他/她的问题。
  • 老实说,我认为你把情况复杂化了。手动调用析构函数没有意义。应该简单地假设在对象仍在使用时销毁它会导致问题。如果有人这样做,那将是 that 代码中的错误。 - 你不能也不应该试图确保这种无意义的情况是不可能的。

标签: php oop destructor


【解决方案1】:

如果您不想调用析构函数,请不要实现它。相反,请使用 private 委托来执行关闭操作。

你的班级:

class Test
{
    private $delegate;

    public function __construct()
    {
        $this->delegate = new TestDelegate;
    }

    public function doTest()
    {
        echo $this->delegate->test."\n";
    }
}

代表:

class TestDelegate
{
    public $test = 'ok';

    public function __destruct()
    {
        $this->test = 'not ok';
        echo __METHOD__." called\n";
    }
}

测试:

$test = new Test;
//$test->__destruct(); // fatal error
$test->doTest(); // prints "ok"
// TestDelegate::__destruct() gets called automatically

现在,这可能会带来其他问题。如果子类实现了构造函数并忘记调用其父构造函数,如何确保委托被注册?如果构造函数被多次调用,它不会破坏事情吗?

要解决这个问题,请创建构造函数 finalprivate 并使用工厂方法:

public static function create()
{
    return new static;
}

【讨论】:

    猜你喜欢
    • 2021-04-24
    • 2017-08-28
    • 2021-10-24
    • 1970-01-01
    • 2019-11-24
    • 2016-01-29
    • 1970-01-01
    • 2013-06-01
    • 2018-12-19
    相关资源
    最近更新 更多