Perl: How to deep copy a blessed object?

I'm looking to do a deep (at this point, shallow may suffice) copy of a blessed object.

Foo Class

package Foo;
our $FOO = new Foo;       # initial run

sub new {
   my $class = shift;
   my $self  = {};
   bless $self, $class;
   return $self;
}

Main Program

use Foo;
my $copy = $Foo::FOO;     # instead of creating a ref, want to deep copy here
$copy->{bar} = 'bar';

bar appears in both $Foo::FOO and $copy . I realize I could create a copy of the object by setting it up as $copy = { %{$Foo::FOO} } , but then it would no longer be blessed; additionally, this would only work for simple data structures (right now not an issue). Is the only way to copy this way and then bless after (eg $copy = bless { %{$Foo::FOO} }, q{Foo}; )?

I'm trying to avoid using Moose, Clone, or other non-Core modules/packages, so please keep that in mind when replying. Bolded so it stands out more :)


The copying should be part of the API. The user of your module would never know what special actions are required upon creation of a new object (consider registering each object in a my hash in your package).

Therefore, provide a clone method for your objects. Inside it, you can use any dirty tricks you like:

sub clone {
    my $self = shift;
    my $copy = bless { %$self }, ref $self;
    $register{$copy} = localtime; # Or whatever else you need to do with a new object.
    # ...
    return $copy;
}

use Storable 'dclone'; ?

$ corelist Storable

Storable was first released with perl v5.7.3

Plus you can fiddle around with Storable hooks to assert finer control over copying your objects (not that I've done it, but that's what the documentation claims).


my $copy = bless { %$self }, ref $self; in @chorba's answer is insufficient. It will only clone the first layer. Any references stored in $self will not be cloned. The consequences of this is...

$obj->{ponies} = [qw(Dash Sparkle Jack)];
$clone = $obj->clone;
push @{$clone->{ponies}}, "Pinkie";
print join ", ", @{$obj->{ponies}};  # Dash Sparkle Jack Pinkie

You might not have any references now, but you probably will later. Or somebody else will stick one into your object. Or they'll subclass and add one.

You can write a deep cloning routine, but it's not simple. I would highly recommend using Clone. It has no dependencies and so you can simply copy Clone.pm into your project.

The other alternative is Storable::dclone, mentioned by @Zaid, which has been in core for a long time.

No matter what you use, providing a clone method on your class is the right thing to do, even if it's just a wrapper around Clone or Storable::dclone. This will shield the user of your object from the details of how your object is cloned.

链接地址: http://www.djcxy.com/p/79370.html

上一篇: 实施深度复制

下一篇: Perl:如何深层复制一个有福的对象?