use Class::MOP::Method::Wrapped;
use Class::MOP::Method::Accessor;
use Class::MOP::Method::Constructor;
-use Class::MOP::Class::Immutable::Class::MOP::Class;
use Carp 'confess';
use Scalar::Util 'blessed', 'weaken';
use Sub::Name 'subname';
use Devel::GlobalDestruction 'in_global_destruction';
-our $VERSION = '0.86';
+our $VERSION = '0.88';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
return if ref($self) eq 'Class::MOP::Class' &&
$self->instance_metaclass eq 'Class::MOP::Instance';
+ return if $self->can('get_mutable_metaclass_name');
+
my @class_list = $self->linearized_isa;
shift @class_list; # shift off $self->name
: ref($super_meta);
($self->isa($super_meta_type))
- || confess "Class::MOP::class_of(" . $self->name . ") => ("
+ || confess "The metaclass of " . $self->name . " ("
. (ref($self)) . ")" . " is not compatible with the " .
- "Class::MOP::class_of(".$superclass_name . ") => ("
+ "metaclass of its superclass, ".$superclass_name . " ("
. ($super_meta_type) . ")";
# NOTE:
# we also need to check that instance metaclasses
# are compatibile in the same the class.
($self->instance_metaclass->isa($super_meta->instance_metaclass))
- || confess "Class::MOP::class_of(" . $self->name . ")->instance_metaclass => (" . ($self->instance_metaclass) . ")" .
+ || confess "The instance metaclass for " . $self->name . " (" . ($self->instance_metaclass) . ")" .
" is not compatible with the " .
- "Class::MOP::class_of(" . $superclass_name . ")->instance_metaclass => (" . ($super_meta->instance_metaclass) . ")";
+ "instance metaclass of its superclass, " . $superclass_name . " (" . ($super_meta->instance_metaclass) . ")";
}
}
my $class = shift;
my $params = @_ == 1 ? $_[0] : {@_};
my $meta_instance = $class->get_meta_instance();
- my $instance = $meta_instance->create_instance();
+ # FIXME:
+ # the code below is almost certainly incorrect
+ # but this is foreign inheritance, so we might
+ # have to kludge it in the end.
+ my $instance = $params->{__INSTANCE__} || $meta_instance->create_instance();
foreach my $attr ($class->get_all_attributes()) {
$attr->initialize_instance_slot($meta_instance, $instance, $params);
}
my ( $current_package, $current_name ) = Class::MOP::get_code_info($body);
- if ( $current_name eq '__ANON__' ) {
+ if ( !defined $current_name || $current_name eq '__ANON__' ) {
my $full_method_name = ($self->name . '::' . $method_name);
subname($full_method_name => $body);
}
$self->get_attribute_map->{$attribute->name} = $attribute;
# invalidate package flag here
- my $e = do { local $@; eval { $attribute->install_accessors() }; $@ };
+ my $e = do {
+ local $@;
+ local $SIG{__DIE__};
+ eval { $attribute->install_accessors() };
+ $@;
+ };
if ( $e ) {
$self->remove_attribute($attribute->name);
die $e;
my $class_name;
if ( $meta_attr and $trait eq $meta_attr->default ) {
-
- # if the trait is the same as the default we try and pick a predictable
- # name for the immutable metaclass
- $class_name = "Class::MOP::Class::Immutable::" . ref($self);
+ # if the trait is the same as the default we try and pick a
+ # predictable name for the immutable metaclass
+ $class_name = 'Class::MOP::Class::Immutable::' . ref($self);
}
else {
- $class_name
- = join( "::", "Class::MOP::Class::Immutable::CustomTrait", $trait,
- "ForMetaClass", ref($self) );
+ $class_name = join '::', 'Class::MOP::Class::Immutable::CustomTrait',
+ $trait, 'ForMetaClass', ref($self);
}
- if ( Class::MOP::is_class_loaded($class_name) ) {
- if ( $class_name->isa($trait) ) {
- return $class_name;
+ return $class_name
+ if Class::MOP::is_class_loaded($class_name);
+
+ my $meta = Class::MOP::Class->create(
+ $class_name,
+ superclasses => [ ref $self ],
+ );
+
+ Class::MOP::load_class($trait);
+ for my $meth ( Class::MOP::Class->initialize($trait)->get_all_methods ) {
+ next if $meta->has_method( $meth->name );
+
+ if ( $meta->find_method_by_name( $meth->name ) ) {
+ $meta->add_around_method_modifier( $meth->name, $meth->body );
}
else {
- confess
- "$class_name is already defined but does not inherit $trait";
+ $meta->add_method( $meth->name, $meth->clone );
}
}
- else {
- my @super = ( $trait, ref($self) );
-
- my $meta = Class::MOP::Class->initialize($class_name);
- $meta->superclasses(@super);
- $meta->make_immutable;
-
- return $class_name;
- }
+ return $class_name;
}
sub _remove_inlined_code {
This method is used to create a new object of the metaclass's
class. Any parameters you provide are used to initialize the
-instance's attributes.
+instance's attributes. A special C<__INSTANCE__> key can be passed to
+provide an already generated instance, rather than having Class::MOP
+generate it for you. This is mostly useful for using Class::MOP with
+foreign classes, which generally generate instances using their own
+constructor.
=item B<< $metaclass->instance_metaclass >>
This will return a L<Class::MOP::Attribute> for the specified
C<$attribute_name>. If the class does not have the specified
-attribute, it returns C<undef>.
+attribute, it returns C<undef>.
-NOTE that get_attribute does not search superclasses, for
-that you need to use C<find_attribute_by_name>.
+NOTE that get_attribute does not search superclasses, for that you
+need to use C<find_attribute_by_name>.
=item B<< $metaclass->has_attribute($attribute_name) >>
The name of a class which will be used as a parent class for the
metaclass object being made immutable. This "trait" implements the
-post-immutability functionlity of the metaclass (but not the
+post-immutability functionality of the metaclass (but not the
transformation itself).
This defaults to L<Class::MOP::Class::Immutable::Trait>.