Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 9 of 9

Thread: clone vs. new

  1. #1
    Senior Coder chump2877's Avatar
    Join Date
    Dec 2004
    Location
    the U.S. of freakin' A.
    Posts
    2,778
    Thanks
    19
    Thanked 155 Times in 146 Posts

    clone vs. new

    Hi friends,

    Quick question about PHP OOP:

    Given the following examples, which is faster and less resource-intensive: Using the "new" keyword or "clone" keyword?

    PHP Code:
    // example #1
    for ($i=0$i<10$i++)
    {
      
    $obj = new Class;
    }

    // example #2
    $class = new Class;
    for (
    $i=0$i<10$i++)
    {
      
    $obj = clone $class;

    Does it really matter which of these examples I use, since they appear to accomplish the same thing? Is one approach better than the other, and if so, why?
    Regards, R.J.

    ---------------------------------------------------------

    Help spread the word! Like my YouTube-to-Mp3 Conversion Script on Facebook !! :)
    [Related videos and tutorials are also available at my YouTube channel and on Dailymotion]
    Get free updates about new software version releases, features, and bug fixes!

  • #2
    Regular Coder
    Join Date
    Sep 2007
    Location
    Grahamstown, South Africa
    Posts
    237
    Thanks
    6
    Thanked 17 Times in 17 Posts
    Cloning doesnt copy internal objects. Whereas new creates NEW objects. They are not the same.

    EG:
    PHP Code:
    <?php

    class foo {
        private 
    $_bar;

        function 
    __construct(){
            
    $this->_bar = new StdClass();
        }
    }

    $obj = new foo;
    $obj2 = clone $obj;
    ?>
    In the above example. foo:$bar would NOT be set in the $obj2 instance.

    At least, this is what I interpret it as. As for speed, I doubt whether there would be any significant overhead difference between the two. But I actually think instantiating the class with 'clone' might be slightly more resource intensive.

    EDIT:

    In my 5 odd years of programming in PHP I have never used cloning. Perhaps somebody more experienced with this technique could explain the usage/benefits/drawbacks of this method? I am also pretty interested in the OP question and the answers which may follow.
    Last edited by idalatob; 09-14-2012 at 02:13 PM.

  • #3
    Regular Coder
    Join Date
    Sep 2007
    Location
    Grahamstown, South Africa
    Posts
    237
    Thanks
    6
    Thanked 17 Times in 17 Posts
    Bet you fou-lo will give us a bad *** answer...

  • #4
    Senior Coder chump2877's Avatar
    Join Date
    Dec 2004
    Location
    the U.S. of freakin' A.
    Posts
    2,778
    Thanks
    19
    Thanked 155 Times in 146 Posts
    In the above example. foo:$bar would NOT be set in the $obj2 instance.
    That's probably what the manual means when it says a "shallow" copy is made...

    Also, is the constructor even called when you clone an object?

    Bet you fou-lo will give us a bad *** answer...
    I'm counting on it!
    Regards, R.J.

    ---------------------------------------------------------

    Help spread the word! Like my YouTube-to-Mp3 Conversion Script on Facebook !! :)
    [Related videos and tutorials are also available at my YouTube channel and on Dailymotion]
    Get free updates about new software version releases, features, and bug fixes!

  • #5
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,987
    Thanks
    4
    Thanked 2,660 Times in 2,629 Posts
    Lol
    As you've mentioned, PHP always performs a shallow copy when calling clone, unless the __clone method is overridden to include the ability to deep copy an object (the objects within an object).
    I'd expect that you'd see no net gain or loss in performance using a shallow copy compared to a new. This excludes any after clone settings.
    I'd expect that you'd see a overall loss in performance when deep copying compared to a new. On top of copying the memory for the existing object, you then need to check if __clone is copying objects within the objects, and it has to repeat the same cycle again.
    Assuming copy on write still applies to objects (which no I cannot be 100% about), if the object is cloned only for read purposes (for whatever reason; I can see no purpose of this), you will gain by using just a clone on objects that don't change. This is because there is simply only one object in memory, pointed at uniquely by 10 different pointers. As soon as you write data from any of them including the original, new ones would be created to take their places. Overall, I'd expect this scenario to never be true.

    You'll see almost no change in performance using either. Instead of concerning the use of performance gain, concern yourself with the logical usage. Deep copying of often done for blocking privacy leaks between objects.
    For example I have an ACL class which has many ACLEntries which I modeled off of Java's ACL interfaces. The rule of the ACL is that you can have at most one positive and one negative ACLEntry per principal in question. So, if I allow an ACLEntry to be added to my ACL, and then the ACLEntry is modified and flipped in being positive / negative, or the principal is altered on it, it could now violate the rules of the ACL. To get around this, I deep clone the ACLEntry objects before adding them to the ACL.

    Edit:
    Since you got another one in there.
    Constructors are not called on a clone. Constructors are only called on a call to new.

    Edit:
    Also, previous example is slightly incorrect. They both have stdclass set as their $_bar member, but they are both the *same* stdclass. Changes in one are reflected in another (ie shallow copied)


    Last edited by Fou-Lu; 09-14-2012 at 02:57 PM.

  • #6
    Senior Coder chump2877's Avatar
    Join Date
    Dec 2004
    Location
    the U.S. of freakin' A.
    Posts
    2,778
    Thanks
    19
    Thanked 155 Times in 146 Posts
    Well if clone performs a shallow copy (and internal objects remain references instead of being recreated), and there is no performance advantage to using one over the other, then I think I'll stick with creating multiple new instances of a class using the "new" keyword...

    I've never considered using clone until now either...sounds like it's unlikely that I will again...

    Thanks guys..
    Regards, R.J.

    ---------------------------------------------------------

    Help spread the word! Like my YouTube-to-Mp3 Conversion Script on Facebook !! :)
    [Related videos and tutorials are also available at my YouTube channel and on Dailymotion]
    Get free updates about new software version releases, features, and bug fixes!

  • #7
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,987
    Thanks
    4
    Thanked 2,660 Times in 2,629 Posts
    If its logical to clone, go with a clone. Like in my ACL example, I had a necessity to clone the object. If you are simply constructing many objects, just use new.
    If you have an object with properties set, and you want to clone that object and its properties, and change only a few of the properties, it makes sense to me that you should clone said object. But you must be aware that objects within the object are not cloned unless specified to do so in the __clone method. Sometimes this is no problem (perhaps a link to a storage location; cloning that is silly unless you intend to use a different storage).

    With my objects, I actually forbid the use of clone by using backtracing on my base Object class. If its not cloned within itself, and if it doesn't implement my ICloneable interface, then the object cannot be cloned at all. ICloneable contains no methods within it, so if my object does implement it I can go ahead and call the clone and it will be chained through the backtrace on Object to construct a shallow clone. __clone can of course be overridden on any class bypassing the ICloneable completely, but overall even with the increased overhead I much prefer an implicit deny of the clone and control it with only things that are cloneable.

  • #8
    Senior Coder chump2877's Avatar
    Join Date
    Dec 2004
    Location
    the U.S. of freakin' A.
    Posts
    2,778
    Thanks
    19
    Thanked 155 Times in 146 Posts
    See my comments in red:

    Quote Originally Posted by Fou-Lu View Post
    If its logical to clone, go with a clone. Like in my ACL example, I had a necessity to clone the object. If you are simply constructing many objects, just use new.
    If you have an object with properties set, and you want to clone that object and its properties, and change only a few of the properties, it makes sense to me that you should clone said object. But you must be aware that objects within the object are not cloned unless specified to do so in the __clone method. Sometimes this is no problem (perhaps a link to a storage location; cloning that is silly unless you intend to use a different storage).

    I agree with that philosophy. If you only need to copy a class that holds a bunch of plain jane class fields -- nothing too complex -- then clone could make sense. Like a PHP equivalent of JSON perhaps, where you are storing a bunch of data and no methods. Or maybe for cloning data that you will later serialize in some way. But both of those things aren't run-of-the-mill, every-day needs (for me at least).

    With my objects, I actually forbid the use of clone by using backtracing on my base Object class. If its not cloned within itself, and if it doesn't implement my ICloneable interface, then the object cannot be cloned at all. ICloneable contains no methods within it, so if my object does implement it I can go ahead and call the clone and it will be chained through the backtrace on Object to construct a shallow clone. __clone can of course be overridden on any class bypassing the ICloneable completely, but overall even with the increased overhead I much prefer an implicit deny of the clone and control it with only things that are cloneable.

    So does "every" class have an implicit __clone() method? Or do you have to at least define it in a base class somewhere, sometimes? Are all classes cloneable? Or only some of them?

    I think, if it were me, I would probably just say to hell with cloning, and override __clone() with my own method that returns an exception...instead of using an interface and backtracing like you are doing (although I understand why you are doing it)...I don;t see a lot of use for it (cloning), and a larger potential to misuse it (and forget that it only does a shallow copy). In my opinion, "new" keyword accomplishes the same thing with same/comparable overhead and really no potential for future headaches.

    Last edited by chump2877; 09-17-2012 at 04:57 AM.
    Regards, R.J.

    ---------------------------------------------------------

    Help spread the word! Like my YouTube-to-Mp3 Conversion Script on Facebook !! :)
    [Related videos and tutorials are also available at my YouTube channel and on Dailymotion]
    Get free updates about new software version releases, features, and bug fixes!

  • #9
    God Emperor Fou-Lu's Avatar
    Join Date
    Sep 2002
    Location
    Saskatoon, Saskatchewan
    Posts
    16,987
    Thanks
    4
    Thanked 2,660 Times in 2,629 Posts
    Every class implicitly uses clone in PHP as its a part of the core OO engine as an overridable method.

    Clone has its uses, although its up to the developer to determine when its appropriate to use it.
    Since PHP does not allow method overloading, its not easily possible to create copy constructors. In languages like java, instead of writing a cloneable object type, you can write a copy constructor that does all the work of the cloner. PHP can't really do this without using some tricky handling of the constructor itself, so the use of the clone override is far more feasible than the use of the copy constructor.

    Unless you have a reason to deny a clone, then I'd suggest not overriding it at all. An example of where you may want to deny a clone as well as use an exception toss in a constructor would be if you had something like a system principal that controlled all actions in the site software. This account would likely desire only one instance, never be instantiated beyond the one instance, and can never be cloned. This is to prevent other parts of the site software from spawning a system permission principal that would allow full control.
    And on the other hand sometimes you need control that is beyond the scope of what a class is capable of easily doing. The ACL is a perfect example of a control that runs on a ruleset, but can be changed externally on the entry itself which could then violate the rules of the acl. There is no other way to get around this; even using observation patterns would be useless as that would assume that the entry would play nice and fire an event to the observer indicating that its changed. While doable when under my control, its not doable to enforce when its beyond my control.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •