# __clone() implementation

- Thread: https://externals.io/message/7270
- Original archive: https://news-web.php.net/php.internals/7270
- Started by Stephane Drouard on 2004-01-22T14:37:11+00:00
- Messages: 5
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #7270 — Stephane Drouard — 2004-01-22T14:37:11+00:00

URL: https://externals.io/message/7270#7270

I'm currently using PHP4 and I'm evaluating PHP5 for its new exciting features.

I have some remarks, split into distinct posts.

The first one is about the current implementation of __clone():

* a derived __clone() can't call parent::__clone() because $that is only declared for the first __clone() call. So a derived __clone() has to include the code of its parent's __clone(). It's not only bad programming, but it can't work when a parent implements private members.
* when a class implements __clone(), all its derived classes have also to implement it to transfer their own members.

There are a several possibilities to get round the first point, but in order to also simplify __clone() implementation, here is a way it could be implemented, close to __construct() implementation:

* the system firstly does a bit for bit copy of the source object,
* then it calls __clone() (which at worst does nothing, if no class implements it),
* __clone() accesses members using $this to handle those (and only those) that need particular actions,
* this is the responsibility of a derived __clone() to call (or not) parent::__clone().

Advantages:
* same behaviour as __construct(), except that $this is already initialized,
* it guaranties that all members will be transfered, by reference for objects, by copy for the others,
* __clone() just needs to be implemented to handle members that need particular actions,
* derived classes do not need to implement __clone() when one of its parents does,
* no more need of $that.

In terms of performance, I don't think this implementation is bad, because a bit for bit copy is certainly faster than an interpreted member-to-member transfer, except if all members have to be handled in a particular way.

I also consider the __clone() implementation not coherent with its calling syntax.
Indeed "$newObj = $obj->__clone();" lets think of an implementation like this:

<?
class Foo {
  function __clone() {
    $o = new Foo($this->..., $this->...);
    $o->...; // eventually
    return $o;
  }
}
?>

Because __clone() is considered as a copy constructor, it could be implemented in a similar way as for object construction, for example: "$newObj = clone $obj;", "clone" being a language keyword.

Regards,
Stephane

---

## #7279 — Marcus Boerger — 2004-01-22T19:27:04+00:00

URL: https://externals.io/message/7270#7279 · In reply to: #7270

Hello Stephane,

you're right $that must be available in the derived __clone().

Thursday, January 22, 2004, 3:37:11 PM, you wrote:

> I'm currently using PHP4 and I'm evaluating PHP5 for its new exciting features.

> I have some remarks, split into distinct posts.

> The first one is about the current implementation of __clone():

> * a derived __clone() can't call parent::__clone() because $that is
> only declared for the first __clone() call. So a derived __clone() has to
> include the code of its parent's __clone(). It's not only bad programming,
> but it can't work when a parent implements private members.
> * when a class implements __clone(), all its derived classes have also
> to implement it to transfer their own members.

> There are a several possibilities to get round the first point, but in
> order to also simplify __clone() implementation, here is a way it could be
> implemented, close to __construct() implementation:

> * the system firstly does a bit for bit copy of the source object,
> * then it calls __clone() (which at worst does nothing, if no class implements it),
> * __clone() accesses members using $this to handle those (and only
> those) that need particular actions,
> * this is the responsibility of a derived __clone() to call (or not) parent::__clone().

> Advantages:
> * same behaviour as __construct(), except that $this is already initialized,
> * it guaranties that all members will be transfered, by reference for objects, by copy for the others,
> * __clone() just needs to be implemented to handle members that need particular actions,
> * derived classes do not need to implement __clone() when one of its parents does,
> * no more need of $that.

> In terms of performance, I don't think this implementation is bad,
> because a bit for bit copy is certainly faster than an interpreted
> member-to-member transfer, except if all members have to be handled in a
> particular way.

> I also consider the __clone() implementation not coherent with its calling syntax.
> Indeed "$newObj = $obj->__clone();" lets think of an implementation like this:

> <?
> class Foo {
>   function __clone() {
>     $o = new Foo($this->..., $this->...);
>     $o->...; // eventually
>     return $o;
>   }
> }
?>>

> Because __clone() is considered as a copy constructor, it could be
> implemented in a similar way as for object construction, for example:
> "$newObj = clone $obj;", "clone" being a language keyword.

> Regards,
> Stephane




-- 
Best regards,
 Marcus                            mailto:helly@php.net

---

## #7476 — Zeev Suraski — 2004-02-02T12:36:22+00:00

URL: https://externals.io/message/7270#7476 · In reply to: #7270

Stephane,

Andi and I have revisited the __clone() implementation and must agree that 
it wasn't quite right (mainly due to it not working with inheritance).
We have rewritten it now (major change!!!) because we didn't want PHP 5 to 
be released with a fundamentally flawed mechanism.

Here's our commit message:

Redesign the `clone()` feature to fix some fundamental flaws in the previous
implementation.
Using clone directly is now done using
$replica = clone $src;
Clone methods must now be declared as follows:
function __clone($that)
{
}
Clone methods in derived classes can call the __clone method of their parent
classes using parent::__clone($that)

Zeev

At 16:37 22/01/2004, Stephane Drouard wrote:
>I'm currently using PHP4 and I'm evaluating PHP5 for its new exciting 
>features.
>
>I have some remarks, split into distinct posts.
>
>The first one is about the current implementation of __clone():
>
>* a derived __clone() can't call parent::__clone() because $that is only 
>declared for the first __clone() call. So a derived __clone() has to 
>include the code of its parent's __clone(). It's not only bad programming, 
>but it can't work when a parent implements private members.
>* when a class implements __clone(), all its derived classes have also to 
>implement it to transfer their own members.
>
>There are a several possibilities to get round the first point, but in 
>order to also simplify __clone() implementation, here is a way it could be 
>implemented, close to __construct() implementation:
>
>* the system firstly does a bit for bit copy of the source object,
>* then it calls __clone() (which at worst does nothing, if no class 
>implements it),
>* __clone() accesses members using $this to handle those (and only those) 
>that need particular actions,
>* this is the responsibility of a derived __clone() to call (or not) 
>parent::__clone().
>
>Advantages:
>* same behaviour as __construct(), except that $this is already initialized,
>* it guaranties that all members will be transfered, by reference for 
>objects, by copy for the others,
>* __clone() just needs to be implemented to handle members that need 
>particular actions,
>* derived classes do not need to implement __clone() when one of its 
>parents does,
>* no more need of $that.
>
>In terms of performance, I don't think this implementation is bad, because 
>a bit for bit copy is certainly faster than an interpreted 
>member-to-member transfer, except if all members have to be handled in a 
>particular way.
>
>I also consider the __clone() implementation not coherent with its calling 
>syntax.
>Indeed "$newObj = $obj->__clone();" lets think of an implementation like this:
>
><?
>class Foo {
>   function __clone() {
>     $o = new Foo($this->..., $this->...);
>     $o->...; // eventually
>     return $o;
>   }
>}
>?>
>
>Because __clone() is considered as a copy constructor, it could be 
>implemented in a similar way as for object construction, for example: 
>"$newObj = clone $obj;", "clone" being a language keyword.
>
>Regards,
>Stephane

---

## #7478 — Ferdinand Beyer — 2004-02-02T18:24:47+00:00

URL: https://externals.io/message/7270#7478 · In reply to: #7270

> Using clone directly is now done using
> $replica = clone $src;
> Clone methods must now be declared as follows:
> function __clone($that)
> {
> }

Finally! I've suggested this change several times before 
(engine2@lists.zend.com) but no one was interested (0 feedback).

But now that it will be included I'm very happy!

-- 
Ferdinand Beyer
<fb@fbeyer.com

---

## #7481 — Ferdinand Beyer — 2004-02-02T18:32:20+00:00

URL: https://externals.io/message/7270#7481 · In reply to: #7270

> Clone methods must now be declared as follows:
> function __clone($that)
> {
> }

I just had a look at zend_compile.c - it seems as if the variable name 
$that was mandantory:

[...]
 || strcmp(CG(active_op_array)->arg_info[0].name, "that")!=0)) { 
                  zend_error(E_COMPILE_ERROR, "The clone method 
must be declared as __clone($that)"); 
[...]

Why shouldn't I be able to name it as I want, e.g. $clone? Don't 
understand the reason for that...

-- 
Ferdinand Beyer
<fb@fbeyer.com
