use Scalar::Util 'blessed', 'weaken';
our $VERSION = '0.65';
+$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use base 'Class::MOP::Module';
# we also need to check that instance metaclasses
# are compatabile in the same the class.
($self->instance_metaclass->isa($meta->instance_metaclass))
- || confess $self->name . "->meta => (" . ($self->instance_metaclass) . ")" .
+ || confess $self->name . "->meta->instance_metaclass => (" . ($self->instance_metaclass) . ")" .
" is not compatible with the " .
- $class_name . "->meta => (" . ($meta->instance_metaclass) . ")";
+ $class_name . "->meta->instance_metaclass => (" . ($meta->instance_metaclass) . ")";
}
}
sub DESTROY {
my $self = shift;
- return if Class::MOP::in_global_destruction; # it'll happen soon anyway and this just makes things more complicated
+ return if Class::MOP::in_global_destruction(); # it'll happen soon anyway and this just makes things more complicated
no warnings 'uninitialized';
return unless $self->name =~ /^$ANON_CLASS_PREFIX/;
## Methods
+sub wrap_method_body {
+ my ( $self, %args ) = @_;
+
+ my $body = delete $args{body}; # delete is for compat
+
+ ('CODE' eq ref($body))
+ || confess "Your code block must be a CODE reference";
+
+ $self->method_metaclass->wrap( $body => (
+ package_name => $self->name,
+ %args,
+ ));
+}
+
sub add_method {
my ($self, $method_name, $method) = @_;
(defined $method_name && $method_name)
}
else {
$body = $method;
- ('CODE' eq ref($body))
- || confess "Your code block must be a CODE reference";
- $method = $self->method_metaclass->wrap(
- $body => (
- package_name => $self->name,
- name => $method_name
- )
- );
+ $method = $self->wrap_method_body( body => $body, name => $method_name );
}
$method->attach_to_class($self);
}
sub alias_method {
- my ($self, $method_name, $method) = @_;
- (defined $method_name && $method_name)
- || confess "You must define a method name";
-
- my $body = (blessed($method) ? $method->body : $method);
- ('CODE' eq ref($body))
- || confess "Your code block must be a CODE reference";
+ my $self = shift;
- $self->add_package_symbol(
- { sigil => '&', type => 'CODE', name => $method_name } => $body
- );
+ $self->add_method(@_);
}
sub has_method {
(defined $method_name && $method_name)
|| confess "You must define a method name";
- return 0 unless exists $self->get_method_map->{$method_name};
- return 1;
+ exists $self->get_method_map->{$method_name};
}
sub get_method {
return;
}
+# check if we can reinitialize
+sub is_pristine {
+ my $self = shift;
+
+ # if any local attr is defined
+ return if $self->get_attribute_list;
+
+ # or any non-declared methods
+ if ( my @methods = values %{ $self->get_method_map } ) {
+ my $metaclass = $self->method_metaclass;
+ foreach my $method ( @methods ) {
+ return if $method->isa("Class::MOP::Method::Generated");
+ # FIXME do we need to enforce this too? return unless $method->isa($metaclass);
+ }
+ }
+
+ return 1;
+}
+
## Class closing
sub is_mutable { 1 }
/],
memoize => {
class_precedence_list => 'ARRAY',
- linearized_isa => 'ARRAY',
+ linearized_isa => 'ARRAY', # FIXME perl 5.10 memoizes this on its own, no need?
+ get_all_methods => 'ARRAY',
+ #get_all_attributes => 'ARRAY', # it's an alias, no need, but maybe in the future
compute_all_applicable_attributes => 'ARRAY',
get_meta_instance => 'SCALAR',
get_method_map => 'SCALAR',
my $original = shift;
confess "Cannot add package symbols to an immutable metaclass"
unless (caller(2))[3] eq 'Class::MOP::Package::get_package_symbol';
- goto $original->body;
+
+ # This is a workaround for a bug in 5.8.1 which thinks that
+ # goto $original->body
+ # is trying to go to a label
+ my $body = $original->body;
+ goto $body;
},
},
});
This returns true if the class has been made immutable.
+=item B<is_pristine>
+
+Checks whether the class has any data that will be lost if C<reinitialize> is
+called.
+
=back
=head2 Inheritance Relationships
Returns the class name of the method metaclass, see L<Class::MOP::Method>
for more information on the method metaclasses.
-=item B<add_method ($method_name, $method)>
+=item B<wrap_method_body(%attrs)>
+
+Wrap a code ref (C<$attrs{body>) with C<method_metaclass>.
-This will take a C<$method_name> and CODE reference to that
-C<$method> and install it into the class's package.
+=item B<add_method ($method_name, $method, %attrs)>
+
+This will take a C<$method_name> and CODE reference or meta method
+objectand install it into the class's package.
+
+You are strongly encouraged to pass a meta method object instead of a
+code reference. If you do so, that object gets stored as part of the
+class's method map, providing more useful information about the method
+for introspection.
B<NOTE>:
This does absolutely nothing special to C<$method>
correct name, and therefore show up correctly in stack traces and
such.
-=item B<alias_method ($method_name, $method)>
-
-This will take a C<$method_name> and CODE reference to that
-C<$method> and alias the method into the class's package.
-
-B<NOTE>:
-Unlike C<add_method>, this will B<not> try to name the
-C<$method> using B<Sub::Name>, it only aliases the method in
-the class's package.
-
=item B<has_method ($method_name)>
This just provides a simple way to check if the class implements
the superclasses, this is basically equivalent to calling
C<SUPER::$method_name>, but it can be dispatched at runtime.
+=item B<alias_method ($method_name, $method)>
+
+B<NOTE>: This method is now deprecated. Just use C<add_method>
+instead.
+
=back
=head2 Method Modifiers