A metaclass extension can be packaged as a subclass or a
role/trait. If you can, we recommend using traits instead of
-subclasses, since it's much easier to combine disparate traits then it
+subclasses, since it's much easier to combine disparate traits than it
is to combine a bunch of subclasses.
When your extensions are implemented as roles, you can apply them with
=head1 ROLES VS TRAITS VS SUBCLASSES
-It is important to understand that B<roles and traits are the same
-thing>. A role can be used as a trait, and a trait is a role. The only
-thing that distinguishes the two is that a trait is packaged in a way
-that lets Moose resolve a short name to a class name. In other words,
-with a trait, the caller can refer to it by a short name like "Big",
-and Moose will resolve it to a class like
-C<MooseX::Embiggen::Meta::Attribute::Role::Big>.
+It is important to understand that B<roles and traits are the same thing>. A
+trait is simply a role applied to a instance. The only thing that may
+distinguish the two is that a trait can be packaged in a way that lets Moose
+resolve a short name to a class name. In other words, with a trait, the caller
+can refer to it by a short name like "Big", and Moose will resolve it to a
+class like C<MooseX::Embiggen::Meta::Attribute::Role::Big>.
See L<Moose::Cookbook::Meta::Recipe3> and
L<Moose::Cookbook::Meta::Recipe5> for examples of traits in action. In
Moose does not provide any simple APIs for consumers to use a subclass
extension, except for attribute metaclasses. The attribute declaration
-parameters include a C<metaclass> parameter a consumer of your
-extension can use to specify your subclass.
+options include a C<metaclass> option a consumer of your extension can
+use to specify your subclass.
This is one reason why implementing an extension as a subclass can be
a poor choice. However, you can force the use of certain subclasses at
);
}
+NOTE: Make sure that your C<init_meta> returns the metaclass object, just as
+C<< Moose->init_meta >> does.
+
=head2 Extensions as Metaclass (and Base Object) Roles
Implementing your extensions as metaclass roles makes your extensions
using this module is that I<it preserves any subclassing or roles
already applied to the user's metaclasses>. This means that your
extension is cooperative I<by default>, and consumers of your
-extension can easily use it with other role-based extensions.
+extension can easily use it with other role-based extensions. Most
+uses of L<Moose::Util::MetaRole> can be handled by L<Moose::Exporter>
+directly; see the L<Moose::Exporter> docs.
package MooseX::Embiggen;
use Moose ();
use Moose::Exporter;
- use Moose::Util::MetaRole;
use MooseX::Embiggen::Role::Meta::Class;
use MooseX::Embiggen::Role::Meta::Attribute;
use MooseX::Embiggen::Role::Meta::Method::Constructor;
use MooseX::Embiggen::Role::Object;
- Moose::Exporter->setup_import_methods( also => 'Moose' );
+ my ($import, $unimport, $init_meta) = Moose::Exporter->build_import_methods(
+ also => ['Moose']
+ metaclass_roles => ['MooseX::Embiggen::Role::Meta::Class'],
+ attribute_metaclass_roles => ['MooseX::Embiggen::Role::Meta::Attribute'],
+ constructor_class_roles =>
+ ['MooseX::Embiggen::Role::Meta::Method::Constructor'],
+ base_class_roles => ['MooseX::Embiggen::Role::Object'],
+ install => [qw(import unimport)],
+ );
sub init_meta {
- shift; # just your package name
+ my $package = shift;
my %options = @_;
-
Moose->init_meta(%options);
-
- my $meta = Moose::Util::MetaRole::apply_metaclass_roles(
- for_class => $options{for_class},
- metaclass_roles => ['MooseX::Embiggen::Role::Meta::Class'],
- attribute_metaclass_roles =>
- ['MooseX::Embiggen::Role::Meta::Attribute'],
- constructor_class_roles =>
- ['MooseX::Embiggen::Role::Meta::Method::Constructor'],
- );
-
- Moose::Util::MetaRole::apply_base_class_roles(
- for_class => $options{for_class},
- roles => ['MooseX::Embiggen::Role::Object'],
- );
-
- return $meta;
+ return $package->$init_meta(%options);
}
As you can see from this example, you can use L<Moose::Util::MetaRole>
also => 'Moose',
);
- sub init_meta { ... }
-
sub embiggen {
my $caller = shift;
$caller->meta()->embiggen(@_);