克隆 PHP 对象并在克隆上设置受保护的 属性

Clone PHP object and set protected property on clone

逻辑有问题

我得到一个需要克隆的对象。

对象是|有一个计算结果。

对象有运行时。

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

(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;
}

我如何克隆以前的对象并在克隆上设置实际运行时间而不使运行时间成为可能 属性 public?

使用魔法方法:

Once the cloning is complete, if a __clone() method is defined, then the newly created object's __clone() method will be called, to allow any necessary properties that need to be changed.

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

class Object
{
    protected $runtime;

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

我建议将此逻辑放在单独的方法中 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 方法