
![]() | ![]() |
13.7. Copy Constructors
13.7.1. Problem
You would
like to provide users of your class with a copy method, or you would
like to copy an object for which no copy method has been provided by
the class.
13.7.2. Solution
Use the
dclone( ) function from the standard Storable
module.use Storable qw(dclone);
use Carp;
sub copy {
my $self = shift;
croak "can't copy class $self" unless ref $self;
my $copy = Storable::dclone($self);
return $copy;
}
13.7.3. Discussion
As described in Recipe 11.12, the Storable
module's dclone function will recursively copy
(virtually) any data structure. It works on objects, too, correctly
giving you back new objects that are appropriately blessed. This
assumes that the underlying types are SCALAR, ARRAY, HASH, or CODE
refs. Things like GLOB and IO refs won't serialize.Some classes already provide methods to copy their objects; others do
not, not so much out of intent as out of neglect. Consider this:sub UNIVERSAL::copy {
my $self = shift;
unless (ref $self) {
require Carp;
Carp::croak("can't copy class $self");
}
require Storable;
my $copy = Storable::dclone($self);
return $copy;
}
Now all objects can be copied, providing they're of the supported
types. Classes that provide their own copy methods
are unaffected, but any class that doesn't
provide its own copy method will pick up this
definition. We placed the require on Storable
within the function call itself so that you load Storable only if you
actually plan to use it. Likewise, we placed the one for Carp inside
the test that will end up using it. By using
require, we delay loading until the module is
actually needed.We also avoid use because it would import things
into our current package. This could be antisocial. From the previous
code snippet, you cannot determine what package you're even in. Just
because we've declared a subroutine named copy to
be in package UNIVERSAL doesn't mean that the code within that
subroutine is in package UNIVERSAL. Rather, it's in whatever package
we are currently compiling into.Some folks would argue that we're being outrageously cavalier by
interjecting a function into somebody else's namespace like
that—especially into all possible class namespaces, as it's in
UNIVERSAL. Cavalier perhaps, but hardly outrageously so; after all,
UNIVERSAL is there to be used. It's no holy namespace, sacrosanct
against any change. Whether this ends up being a very stupid thing or
a very clever thing is not up to Perl to decide, or prevent.
13.7.4. See Also
Recipe 11.12; Recipe 13.9; the documentation for the standard Storable
modules; the section on Inheritance in the introduction to this
chapter; the section on "UNIVERSAL: The Ultimate Ancestor Class" in
Chapter 12 of Programming Perl
![]() | ![]() | ![]() |
13.6. Cloning Constructors | ![]() | 13.8. Invoking Methods Indirectly |

Copyright © 2003 O'Reilly & Associates. All rights reserved.