【问题标题】:Clone PHP object and set protected property on clone克隆 PHP 对象并在克隆时设置受保护的属性
【发布时间】:2018-08-08 09:45:49
【问题描述】:

我遇到了一个逻辑问题。

我有一个需要克隆的对象。

对象是|具有计算结果。

对象有一个运行时。

在某些情况下,克隆对象比再次计算结果更快

(f.e. 相同的参数 ^= 相同的结果).

但必须不复制运行时。

运行时将是确定我可以使用相同结果(对象)的时间。

例子:

class Object
{
    protected $runtime;

    public function getRuntime()
    {
        return $this->runtime;
    }

    public function doSome(/*...*/)
    {
        $start = microtime(true);
        // ... the heavy work ...
        // ...
        $this->runtime = microtime(true) - $start;
    }
}

$objects = [];
while (/*...*/) {
    if (count($objects) > 0) {
        $start = microtime(true);
        if (/*check if would get the same result as the previous one*/) {
            $object = clone end($objects);
            // MUST change the runtime here on the clone 
            // but i should not make :runtime public
            $object->runtime = microtime(true) - $start; // :(
            $objects[] = $object;
            continue;
        }
    }
    $object = new Object();
    $object->doSome(/*...*/);
    $objects[] = $object;
}

我如何克隆前一个对象并在克隆上设置实际运行时而不使运行时属性公开?

【问题讨论】:

  • 请不要将解决方案添加到您的问题中。相反,您可以通过单击复选标记来选择下面的答案,或者自己回答问题。您的问题已回滚到以前的状态。欲了解更多信息,请访问help center。

标签: php object properties clone


【解决方案1】:

我建议将此逻辑放在单独的方法Object::clone() 中,如下所示:

class Object
{
    protected $runtime;

    public function getRuntime()
    {
        return $this->runtime;
    }

    public function doSome(/*...*/)
    {
        $start = microtime(true);
        // ... the heavy work ...
        // ...
        $this->runtime = microtime(true) - $start;
    }

    public static function clone($clonable, $runtime)
    {
        $clone = clone $clonable;
        $clone->runtime = $runtime; // we can access it since we are in Object scope
        return $clone;
    }
}

$objects = [];
while (/*...*/) {
    if (count($objects) > 0) {
        $start = microtime(true);
        if (/*check if would get the same result as the previous one*/) {
            $object = Object::clone(end($objects), microtime(true) - $start);
            $objects[] = $object;
            continue;
        }
    }
    $object = new Object();
    $object->doSome(/*...*/);
    $objects[] = $object;
}

另一种选择只是为runtime 属性实现setter 方法

【讨论】:

  • 非常感谢。对我有意义。除了我真的不明白为什么我们可以从“外部”在对象上设置受保护的属性。但这有效。伟大的! :)
  • 由于我不允许在我自己的问题上添加解决方案示例:我计算克隆方法中克隆对象的时间。然后我将“克隆时间”添加到给定参数$runtime。这提供了创建该对象的完整时间。也许您可以将其添加到您的解决方案中。 $start = microtime(true); $clone = clone $clonable; $clone->runtime = $runtime + (microtime(true) - $start); return $clone;
  • 好的,我认为这取决于您的上下文在哪里计算runtime,是的,它也可以在clone 方法中完成。还有php.net docs (about private and protected properties access)
【解决方案2】:

使用魔法:

克隆完成后,如果定义了 __clone() 方法,则将调用新创建对象的 __clone() 方法,以允许任何需要更改的必要属性。

http://php.net/manual/en/language.oop5.cloning.php#object.clone

class Object
{
    protected $runtime;

    public function __clone() {
        //set $this->runtime
    }
}    

【讨论】:

  • 是否可以将$start 变量传递给该方法?
  • 你不能。 Fatal error: Method Object::__clone() cannot accept any arguments
猜你喜欢
  • 2014-02-08
  • 2016-08-05
  • 2015-02-08
  • 2011-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
相关资源
最近更新 更多