Цепочка методов PHP и CLONE

Мне кое-что интересно.

Уважаемый разработчик предложил использовать "return clone $ this" вместо простого "return $ this", и в итоге он на время покинул проект с открытым исходным кодом и так и не ответил на мой "почему?" вопрос, поэтому мне любопытно, есть ли в этом ЛЮБАЯ польза.

Итак, в качестве примера обычного цепного метода у нас может быть что-то вроде этого:

function setProperty($arg) {
    this->property = $arg;
    return $this;
 }

Его пример был примерно таким:

function setProperty($arg) {
     this->property = $arg;
     return clone $this;
}

У меня сложилось впечатление, что он ошибался в этом, потому что все, что он делал, это делал копию объекта на каждом шаге, который был бы недоступен.

Итак, если бы мы использовали его метод и сказали бы что-то вроде этого ...

class foo {
     public $value;
     function setA($arg) {
        $this->value = $arg;
        return clone $this;
     }

     function setB($arg) {
         $this->value = $arg;
         return clone $this;
     }

     function setB($arg) {
         $this->value = $arg;
         return clone $this;
     }

     function print() {
         print $this->value;
     }
}

И у нас была такая строка ($ obj - это экземпляр класса foo):

$obj->setA('a')->setB('b')->setC('c')->print();

Это должно закончиться печатью c независимо от того, выполнено ли это с помощью clone $ this или просто $ this.

Тем не мение...

$obj->setA('a')->setB('b')->setC('c');
$obj->print();

должен напечатать a, поскольку только первый шаг изменит исходный объект. Второй шаг изменит клонированный объект из первого шага, а третий шаг изменит объект, переданный ему из второго шага.

но опять же, если вы пошли с:

$obj = $obj->setA('a')->setB('b')->setC('c');
$obj->print();

Я бы поверил, что это также напечатает c в любом методе.

Если бы мы изначально объявили $ value как static, тогда все эти различные варианты должны напечатать c.

Если я понимаю, как все это работает, я считаю, что прав, и не вижу абсолютно никакой пользы в использовании «return clone $ this» вместо «return $ this». Или я что-то упускаю, или я полностью ошибаюсь в своих предположениях?

Спасибо!

Родни


person Rodney    schedule 20.03.2014    source источник


Ответы (1)


Я не думаю, что вы когда-нибудь захотите изменить состояние текущего объекта, а затем вернуть клон. Вместо этого вы должны клонировать , а затем изменять. Пример,

class Foo {
     private $value;

     function setValue($arg) {
        $clone = clone $this;
        $clone->value = $arg;
        return $clone;
     }

     function printValue() {
         echo $this->value.PHP_EOL;
     }
}

Таким образом ваш объект становится неизменным.

Пример использования:

$a = (new Foo)->setValue('a');
$b = $a->setValue('b');

$a->printValue();
$b->printValue();

Это напечатает

a
b

Таким образом $a не испортится, когда вы "измените" $b.

person mpen    schedule 21.02.2015