use Carp 'confess';
use Scalar::Util 'blessed', 'weaken';
-our $VERSION = '0.78';
+our $VERSION = '0.79';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
: ref($super_meta);
($self->isa($super_meta_type))
- || confess $self->name . "->meta => (" . (ref($self)) . ")" .
- " is not compatible with the " .
- $superclass_name . "->meta => (" . ($super_meta_type) . ")";
+ || confess "Class::MOP::class_of(" . $self->name . ") => ("
+ . (ref($self)) . ")" . " is not compatible with the " .
+ "Class::MOP::class_of(".$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 $self->name . "->meta->instance_metaclass => (" . ($self->instance_metaclass) . ")" .
+ || confess "Class::MOP::class_of(" . $self->name . ")->instance_metaclass => (" . ($self->instance_metaclass) . ")" .
" is not compatible with the " .
- $superclass_name . "->meta->instance_metaclass => (" . ($super_meta->instance_metaclass) . ")";
+ "Class::MOP::class_of(" . $superclass_name . ")->instance_metaclass => (" . ($super_meta->instance_metaclass) . ")";
}
}
sub rebless_instance {
my ($self, $instance, %params) = @_;
- my $old_metaclass;
- if ($instance->can('meta')) {
- ($instance->meta->isa('Class::MOP::Class'))
- || confess 'Cannot rebless instance if ->meta is not an instance of Class::MOP::Class';
- $old_metaclass = $instance->meta;
- }
- else {
- $old_metaclass = $self->initialize(ref($instance));
- }
+ my $old_metaclass = Class::MOP::class_of($instance);
- my $meta_instance = $self->get_meta_instance();
+ my $old_class = $old_metaclass ? $old_metaclass->name : blessed($instance);
+ $self->name->isa($old_class)
+ || confess "You may rebless only into a subclass of ($old_class), of which (". $self->name .") isn't.";
- $self->name->isa($old_metaclass->name)
- || confess "You may rebless only into a subclass of (". $old_metaclass->name ."), of which (". $self->name .") isn't.";
+ $old_metaclass->rebless_instance_away($instance, $self, %params)
+ if $old_metaclass;
+
+ my $meta_instance = $self->get_meta_instance();
# rebless!
# we use $_[1] here because of t/306_rebless_overload.t regressions on 5.8.8
$instance;
}
+sub rebless_instance_away {
+ # this intentionally does nothing, it is just a hook
+}
+
# Inheritance
sub superclasses {
sub immutable_transformer { $_[0]->{immutable_transformer} }
sub _set_immutable_transformer { $_[0]->{immutable_transformer} = $_[1] }
+sub make_immutable {
+ my $self = shift;
+
+ return if $self->is_immutable;
+
+ my $transformer = $self->immutable_transformer
+ || $self->_make_immutable_transformer(@_);
+
+ $self->_set_immutable_transformer($transformer);
+
+ $transformer->make_metaclass_immutable;
+}
+
{
my %Default_Immutable_Options = (
read_only => [qw/superclasses/],
cannot_call => [
- qw/
+ qw(
add_method
alias_method
remove_method
add_attribute
remove_attribute
remove_package_symbol
- /
+ )
],
memoize => {
class_precedence_list => 'ARRAY',
},
);
- sub make_immutable {
- my $self = shift;
-
- return if $self->is_immutable;
-
- my $transformer = $self->immutable_transformer
- || Class::MOP::Immutable->new(
- $self,
- %Default_Immutable_Options,
- @_
- );
+ sub _default_immutable_transformer_options {
+ return %Default_Immutable_Options;
+ }
+}
- $self->_set_immutable_transformer($transformer);
+sub _make_immutable_transformer {
+ my $self = shift;
- $transformer->make_metaclass_immutable;
- }
+ Class::MOP::Immutable->new(
+ $self,
+ $self->_default_immutable_transformer_options,
+ @_
+ );
}
sub make_mutable {
=head1 DESCRIPTION
-This is the largest and most complex part of the Class::MOP
-meta-object protocol. It controls the introspection and manipulation
-of Perl 5 classes, and it can create them as wlel. The best way to
-understand what this module can do, is to read the documentation for
-each of its methods.
+The Class Protocol is the largest and most complex part of the
+Class::MOP meta-object protocol. It controls the introspection and
+manipulation of Perl 5 classes, and it can create them as well. The
+best way to understand what this module can do, is to read the
+documentation for each of its methods.
=head1 INHERITANCE
This method clones an existing object instance. Any parameters you
provide are will override existing attribute values in the object.
-This is a convience method for cloning an object instance, then
+This is a convenience method for cloning an object instance, then
blessing it into the appropriate package.
You could implement a clone method in your class, using this method:
attributes. Any existing attributes that are already set will be
overwritten.
+Before reblessing the instance, this method will call
+C<rebless_instance_away> on the instance's current metaclass. This method
+will be passed the instance, the new metaclass, and any parameters
+specified to C<rebless_instance>. By default, C<rebless_instance_away>
+does nothing; it is merely a hook.
+
=item B<< $metaclass->new_object(%params) >>
This method is used to create a new object of the metaclass's
Returns the class name of the instance metaclass, see
L<Class::MOP::Instance> for more information on the instance
-metaclasses.
+metaclass.
=item B<< $metaclass->get_meta_instance >>
Remove the named method from the class. This method returns the
L<Class::MOP::Method> object for the method.
+=item B<< $metaclass->method_metaclass >>
+
+Returns the class name of the method metaclass, see
+L<Class::MOP::Method> for more information on the method metaclass.
+
+=item B<< $metaclass->wrapped_method_metaclass >>
+
+Returns the class name of the wrapped method metaclass, see
+L<Class::MOP::Method::Wrapped> for more information on the wrapped
+method metaclass.
+
=back
=head2 Attribute introspection and creation
longer call methods which alter the class, such as adding or removing
methods or attributes.
-Making a class immutable lets us optimize the class by inlning some
+Making a class immutable lets us optimize the class by inlining some
methods, and also allows us to optimize some methods on the metaclass
object itself.
Method modifiers work by wrapping the original method and then
replacing it in the class's symbol table. The wrappers will handle
-calling all the modifiers in the appropariate orders and preserving
-the calling context for the original method.
+calling all the modifiers in the appropriate order and preserving the
+calling context for the original method.
The return values of C<before> and C<after> modifiers are
ignored. This is because their purpose is B<not> to filter the input
=back
+=head2 Introspection
+
+=over 4
+
+=item B<< Class::MOP::Class->meta >>
+
+This will return a L<Class::MOP::Class> instance for this class.
+
+It should also be noted that L<Class::MOP> will actually bootstrap
+this module by installing a number of attribute meta-objects into its
+metaclass.
+
+=back
+
=head1 AUTHORS
Stevan Little E<lt>stevan@iinteractive.comE<gt>