use Carp 'confess';
use Scalar::Util 'blessed', 'reftype';
-use Hash::Util 'lock_keys';
use Sub::Name 'subname';
use B 'svref_2object';
+use Clone ();
our $VERSION = '0.03';
# NOTE:
# we need to protect the integrity of the
# Class::MOP::Class singletons here, they
- # should not be cloned
+ # should not be cloned.
return $instance if $instance->isa('Class::MOP::Class');
bless $class->clone_instance($instance, @_) => blessed($instance);
}
-#{
-# sub _deep_clone {
-# my ($object, $cache) = @_;
-# return $object unless ref($object);
-# # check for an active cache
-# return _deep_clone_ref($object, ($cache = {}), 'HASH') if not defined $cache;
-# # if we have it in the cache them return the cached clone
-# return $cache->{$object} if exists $cache->{$object};
-# # now try it as an object, which will in
-# # turn try it as ref if its not an object
-# # and store it in case we run into a circular ref
-# $cache->{$object} = _deep_clone_object($object, $cache);
-# }
-#
-# sub _deep_clone_object {
-# my ($object, $cache) = @_;
-# # check to see if its an object, with a clone method
-# # or if we have an object, with no clone method, then
-# # we will respect its encapsulation, and not muck with
-# # its internals. Basically, we assume it does not want
-# # to be cloned
-# return $cache->{$object} = ($object->can('clone') ? $object->clone() : $object)
-# if blessed($object);
-# return $cache->{$object} = _deep_clone_ref($object, $cache);
-# }
-#
-# sub _deep_clone_ref {
-# my ($object, $cache, $ref_type) = @_;
-# $ref_type ||= ref($object);
-# my ($clone, $tied);
-# if ($ref_type eq 'HASH') {
-# $clone = {};
-# tie %{$clone}, ref $tied if $tied = tied(%{$object});
-# %{$clone} = map { ref($_) ? _deep_clone($_, $cache) : $_ } %{$object};
-# }
-# elsif ($ref_type eq 'ARRAY') {
-# $clone = [];
-# tie @{$clone}, ref $tied if $tied = tied(@{$object});
-# @{$clone} = map { ref($_) ? _deep_clone($_, $cache) : $_ } @{$object};
-# }
-# elsif ($ref_type eq 'REF' or $ref_type eq 'SCALAR') {
-# my $var = "";
-# $clone = \$var;
-# tie ${$clone}, ref $tied if $tied = tied(${$object});
-# ${$clone} = _deep_clone(${$object}, $cache);
-# }
-# else {
-# # shallow copy reference to code, glob, regex
-# $clone = $object;
-# }
-# # store it in our cache
-# $cache->{$object} = $clone;
-# # and return the clone
-# return $clone;
-# }
-#}
-
sub clone_instance {
my ($class, $instance, %params) = @_;
(blessed($instance))
|| confess "You can only clone instances, \$self is not a blessed instance";
# NOTE:
- # this should actually do a deep clone
- # instead of this cheap hack. I will
- # add that in later.
- # (use the Class::Cloneable::Util code)
- my $clone = { %{$instance} }; #_deep_clone($instance);
+ # This will deep clone, which might
+ # not be what you always want. So
+ # the best thing is to write a more
+ # controled &clone method locally
+ # in the class (see Class::MOP)
+ my $clone = Clone::clone($instance);
foreach my $attr ($class->compute_all_applicable_attributes()) {
my $init_arg = $attr->init_arg();
# try to fetch the init arg from the %params ...
use strict;
use warnings;
-use Test::More tests => 32;
+use Test::More tests => 36;
use Test::Exception;
BEGIN {
$foo_meta->clone_object($meta);
} '... this dies as expected';
+# test stuff
+
+{
+ package FooBar;
+ use metaclass;
+
+ FooBar->meta->add_attribute('test');
+}
+
+my $attr = FooBar->meta->get_attribute('test');
+isa_ok($attr, 'Class::MOP::Attribute');
+
+my $attr_clone = $attr->clone();
+isa_ok($attr_clone, 'Class::MOP::Attribute');
+
+isnt($attr, $attr_clone, '... we successfully cloned our attributes');
+is($attr->associated_class,
+ $attr_clone->associated_class,
+ '... we successfully did not clone our associated metaclass');
+
my $attr_clone = $attr->clone();
isa_ok($attr_clone, 'Class::MOP::Attribute');
- isnt($attr, $attr_clone, '... but they are different instnaces');
+ isnt($attr, $attr_clone, '... but they are different instances');
is_deeply($attr, $attr_clone, '... but they are the same inside');
}
my $attr_clone = $attr->clone();
isa_ok($attr_clone, 'Class::MOP::Attribute');
- isnt($attr, $attr_clone, '... but they are different instnaces');
+ isnt($attr, $attr_clone, '... but they are different instances');
is_deeply($attr, $attr_clone, '... but they are the same inside');
}