views:

156

answers:

3

I'm reading Programming Perl, and I found this code snippet:

sub new {
    my $invocant = shift;
    my $class   = ref($invocant) || $invocant;
    my $self = {
        color  => "bay",
        legs   => 4,
        owner  => undef,
        @_,                 # Override previous attributes
    };
    return bless $self, $class;
}

With constructors like this one, what's the benefit of calling new on an object instance? I assume that it's what it's for, right? My guess is that if anyone would want to write such a constructor, he would have to add some more code that copies the attributes of the first object to the one about to be created.

+11  A: 

So you can construct another object of the same class without knowing what the original class's object is - this can make for some really neat compact factory pattern.

As an example, this is useful when you have resource objects you need to construct, as need arises and the cost of computing WHICH kind of resource object is high (say, a long-running DB query). Therefore, a factory would see if it was passed an old resource object and if so, create one just like it by merely calling $old_object->new() - avoiding the resource cost of re-computing the kind of resource.

As another example, if you have class hierarchy denoting animals, and a factory for constructing new animals in a simulation, you could call $newborn = $factory->make_new_animal($mother) with the factory implementation being merely $object->new()

DVK
The function doesn't copy anything from the original instance. It just gets the class name using `ref($self)`, nothing else. After that, it creates a completely new object.
Lukáš Lalinský
Lucas - yep, didn't read the code carefully enough... itchy fingers :) I edited the "copy constructor" reference out by the time you commented on it :)
DVK
@DVK: perhaps you could show an example?
ysth
As an example, if you have resource objects you need to construct, as need arises. The cost of computing WHICH kind of resource object is high (say, a long-running DB query). Therefore, a factory would see if it was passed an old resource object and if so, create one just like it by merely calling $old_object->new()
DVK
As another example, if you have class hierarchy denoting animals, and a factory for constructing enw animals in a simulation, you could call `$newborn = $factory->make_new_animal($mother)` with the factory implementation being merely $object->new()
DVK
+6  A: 

I don't see any real benefit. You can always just do ref($obj)->new or have a method to do $obj->clone; that way you aren't left wondering which of those two $object->new is doing.

ysth
ysth - see my answer. There are some really neat factory-like things thet can be implemented if your base class has this "make one like me" new method.
DVK
@DVK: better done with a make_one_like_me method, then.
ysth
Can be done -yes. "better" - debatable. I find both OK, with the one from the book more obvious and straighforward by a thin margin.
DVK
"obvious" on the caller side > "obvious" on the callee side
ysth
+5  A: 

As others have said, it's to allow for the polymorphic creation of a new object instance without having to be aware of the type of that instance.

As for object cloning, I normally write explicit clone() or copy() methods that can properly copy attributes and other data over, but there's no reason why new() can't take care of this role, as long as it's documented clearly. However I see two advantages into defining them separately:

  1. being able to use a different class (a child, or a mixin/role (e.g. a Moose role)) to override various behaviour
  2. the potential of making the code clearer, such as if the steps required to create a new "empty" object is very different than those in cloning an existing object.
Ether