Heray-Was-Here
Server : Apache
System : Linux vps103298.mylogin.co 4.18.0-513.11.1.el8_9.x86_64 #1 SMP Wed Jan 17 02:00:40 EST 2024 x86_64
User : calvet ( 273824)
PHP Version : 7.4.33
Disable Function : NONE
Directory :  /usr/local/share/man/man3/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //usr/local/share/man/man3/Moose::Cookbook::Extending::ExtensionOverview.3pm
.\" Automatically generated by Pod::Man 4.11 (Pod::Simple 3.35)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings.  \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote.  \*(C+ will
.\" give a nicer C++.  Capital omega is used to do unbreakable dashes and
.\" therefore won't be available.  \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
.    ds -- \(*W-
.    ds PI pi
.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
.    ds L" ""
.    ds R" ""
.    ds C` ""
.    ds C' ""
'br\}
.el\{\
.    ds -- \|\(em\|
.    ds PI \(*p
.    ds L" ``
.    ds R" ''
.    ds C`
.    ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el       .ds Aq '
.\"
.\" If the F register is >0, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD.  Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{\
.    if \nF \{\
.        de IX
.        tm Index:\\$1\t\\n%\t"\\$2"
..
.        if !\nF==2 \{\
.            nr % 0
.            nr F 2
.        \}
.    \}
.\}
.rr rF
.\" ========================================================================
.\"
.IX Title "Moose::Cookbook::Extending::ExtensionOverview 3"
.TH Moose::Cookbook::Extending::ExtensionOverview 3 "2021-11-07" "perl v5.26.3" "User Contributed Perl Documentation"
.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
Moose::Cookbook::Extending::ExtensionOverview \- Moose extension overview
.SH "VERSION"
.IX Header "VERSION"
version 2.2201
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
Moose provides several ways in which extensions can hook into Moose
and change its behavior. Moose also has a lot of behavior that can be
changed. This recipe will provide an overview of each extension method
and give you some recommendations on what tools to use.
.PP
If you haven't yet read the recipes on metaclasses, go read those
first. You can't write Moose extensions without understanding the
metaclasses, and those recipes also demonstrate some basic extension
mechanisms, such as metaclass subclasses and traits.
.SS "Playing Nice With Others"
.IX Subsection "Playing Nice With Others"
One of the goals of this overview is to help you build extensions that
cooperate well with other extensions. This is especially important if
you plan to release your extension to \s-1CPAN.\s0
.PP
Moose comes with several modules that exist to help your write
cooperative extensions. These are Moose::Exporter and
Moose::Util::MetaRole. By using these two modules, you will ensure
that your extension works with both the Moose core features and any
other \s-1CPAN\s0 extension using those modules.
.SH "PARTS OF Moose YOU CAN EXTEND"
.IX Header "PARTS OF Moose YOU CAN EXTEND"
The types of things you might want to do in Moose extensions fall into
a few broad categories.
.SS "Metaclass Extensions"
.IX Subsection "Metaclass Extensions"
One way of extending Moose is by extending one or more Moose
metaclasses. For example, in Moose::Cookbook::Meta::Table_MetaclassTrait we saw
a metaclass role that added a \f(CW\*(C`table\*(C'\fR attribute to the
metaclass. If you were writing an \s-1ORM,\s0 this would be a logical
extension.
.PP
Many of the Moose extensions on \s-1CPAN\s0 work by providing an attribute
metaclass role. For example, the MooseX::Aliases module
provides an attribute metaclass trait that lets you specify aliases
to install for methods and attribute accessors.
.PP
A metaclass extension can be packaged as a role/trait or a subclass. If you
can, we recommend using traits instead of subclasses, since it's much easier
to combine disparate traits than it is to combine a bunch of subclasses.
.PP
When your extensions are implemented as roles, you can apply them with
the Moose::Util::MetaRole module.
.SS "Providing Sugar Functions"
.IX Subsection "Providing Sugar Functions"
As part of a metaclass extension, you may also want to provide some
sugar functions, just like Moose.pm does. Moose provides a
helper module called Moose::Exporter that makes this much
simpler. We will be use Moose::Exporter in several of the extension
recipes.
.SS "Object Class Extensions"
.IX Subsection "Object Class Extensions"
Another common Moose extension technique is to change the default object
class's behavior. As with metaclass extensions, this can be done with a
role/trait or with a subclass. For example, MooseX::StrictConstructor
extension applies a trait that makes the constructor reject arguments which
don't match its attributes.
.PP
Object class extensions often include metaclass extensions as well. In
particular, if you want your object extension to work when a class is
made immutable, you may need to modify the behavior of some or all of the
Moose::Meta::Instance, Moose::Meta::Method::Constructor, and
Moose::Meta::Method::Destructor objects.
.PP
The Moose::Util::MetaRole module lets you apply roles to the base
object class, as well as the meta classes just mentioned.
.SS "Providing a Role"
.IX Subsection "Providing a Role"
Some extensions come in the form of a role for you to consume. The
MooseX::Object::Pluggable extension is a great example of this. In
fact, despite the \f(CW\*(C`MooseX\*(C'\fR name, it does not actually change anything
about Moose's behavior. Instead, it is just a role that an object
which wants to be pluggable can consume.
.PP
If you are implementing this sort of extension, you don't need to do
anything special. You simply create a role and document that it should
be used via the normal \f(CW\*(C`with\*(C'\fR sugar:
.PP
.Vb 1
\&   package MyApp::User;
\&
\&   use Moose;
\&
\&   with \*(AqMy::Role\*(Aq;
.Ve
.PP
Don't use \*(L"MooseX\*(R" in the name for such packages.
.SS "New Types"
.IX Subsection "New Types"
Another common Moose extension is a new type for the Moose type
system. In this case, you simply create a type in your module. When
people load your module, the type is created, and they can refer to it
by name after that. The MooseX::Types::URI and
MooseX::Types::DateTime distributions are two good examples of how
this works. These both build on top of the MooseX::Types extension.
.SH "ROLES VS TRAITS VS SUBCLASSES"
.IX Header "ROLES VS TRAITS VS SUBCLASSES"
It is important to understand that \fBroles and traits are the same thing\fR. 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 \*(L"Big\*(R", and Moose will resolve it to a
class like \f(CW\*(C`MooseX::Embiggen::Meta::Attribute::Role::Big\*(C'\fR.
.PP
See Moose::Cookbook::Meta::Labeled_AttributeTrait and
Moose::Cookbook::Meta::Table_MetaclassTrait for examples of traits in
action. In particular, both of these recipes demonstrate the trait resolution
mechanism.
.PP
Implementing an extension as a (set of) metaclass or base object
role(s) will make your extension more cooperative. It is hard for an
end-user to effectively combine together multiple metaclass
subclasses, but it is very easy to combine roles.
.SH "USING YOUR EXTENSION"
.IX Header "USING YOUR EXTENSION"
There are a number of ways in which an extension can be applied. In
some cases you can provide multiple ways of consuming your extension.
.SS "Extensions as Metaclass Traits"
.IX Subsection "Extensions as Metaclass Traits"
If your extension is available as a trait, you can ask end users to
simply specify it in a list of traits. Currently, this only works for
(class) metaclass and attribute metaclass traits:
.PP
.Vb 1
\&  use Moose \-traits => [ \*(AqBig\*(Aq, \*(AqBlue\*(Aq ];
\&
\&  has \*(Aqanimal\*(Aq => (
\&      traits => [ \*(AqBig\*(Aq, \*(AqBlue\*(Aq ],
\&      ...
\&  );
.Ve
.PP
If your extension applies to any other metaclass, or the object base
class, you cannot use the trait mechanism.
.PP
The benefit of the trait mechanism is that is very easy to see where a
trait is applied in the code, and consumers have fine-grained control
over what the trait applies to. This is especially true for attribute
traits, where you can apply the trait to just one attribute in a
class.
.SS "Extensions as Metaclass (and Base Object) Roles"
.IX Subsection "Extensions as Metaclass (and Base Object) Roles"
Implementing your extensions as metaclass roles makes your extensions
easy to apply, and cooperative with other role-based extensions for
metaclasses.
.PP
Just as with a subclass, you will probably want to package your
extensions for consumption with a single module that uses
Moose::Exporter. However, in this case, you will use
Moose::Util::MetaRole to apply all of your roles. The advantage of
using this module is that \fIit preserves any subclassing or roles
already applied to the user's metaclasses\fR. This means that your
extension is cooperative \fIby default\fR, and consumers of your
extension can easily use it with other role-based extensions. Most
uses of Moose::Util::MetaRole can be handled by Moose::Exporter
directly; see the Moose::Exporter docs.
.PP
.Vb 1
\&  package MooseX::Embiggen;
\&
\&  use Moose::Exporter;
\&
\&  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(
\&      class_metaroles => {
\&          class     => [\*(AqMooseX::Embiggen::Role::Meta::Class\*(Aq],
\&          attribute => [\*(AqMooseX::Embiggen::Role::Meta::Attribute\*(Aq],
\&          constructor =>
\&              [\*(AqMooseX::Embiggen::Role::Meta::Method::Constructor\*(Aq],
\&      },
\&      base_class_roles => [\*(AqMooseX::Embiggen::Role::Object\*(Aq],
\&  );
.Ve
.PP
As you can see from this example, you can use Moose::Util::MetaRole
to apply roles to any metaclass, as well as the base object class. If
some other extension has already applied its own roles, they will be
preserved when your extension applies its roles, and vice versa.
.SS "Providing Sugar"
.IX Subsection "Providing Sugar"
With Moose::Exporter, you can also export your own sugar functions:
.PP
.Vb 1
\&  package MooseX::Embiggen;
\&
\&  use Moose::Exporter;
\&
\&  Moose::Exporter\->setup_import_methods(
\&      with_meta       => [\*(Aqembiggen\*(Aq],
\&      class_metaroles => {
\&          class => [\*(AqMooseX::Embiggen::Role::Meta::Class\*(Aq],
\&      },
\&  );
\&
\&  sub embiggen {
\&      my $meta = shift;
\&      $meta\->embiggen(@_);
\&  }
.Ve
.PP
And then the consumer of your extension can use your \f(CW\*(C`embiggen\*(C'\fR sub:
.PP
.Vb 1
\&  package Consumer;
\&
\&  use Moose;
\&  use MooseX::Embiggen;
\&
\&  extends \*(AqThing\*(Aq;
\&
\&  embiggen ...;
.Ve
.PP
This can be combined with metaclass and base class roles quite easily.
.SS "More advanced extensions"
.IX Subsection "More advanced extensions"
Providing your extension simply as a set of traits that gets applied to the
appropriate metaobjects is easy, but sometimes not sufficient. For instance,
sometimes you need to supply not just a base object role, but an actual base
object class (due to needing to interact with existing systems that only
provide a base class). To write extensions like this, you will need to provide
a custom \f(CW\*(C`init_meta\*(C'\fR method in your exporter. For instance:
.PP
.Vb 1
\&  package MooseX::Embiggen;
\&
\&  use Moose::Exporter;
\&
\&  my ($import, $unimport, $init_meta) = Moose::Exporter\->build_import_methods(
\&      install         => [\*(Aqimport\*(Aq, \*(Aqunimport\*(Aq],
\&      with_meta       => [\*(Aqembiggen\*(Aq],
\&      class_metaroles => {
\&          class => [\*(AqMooseX::Embiggen::Role::Meta::Class\*(Aq],
\&      },
\&  );
\&
\&  sub embiggen {
\&      my $meta = shift;
\&      $meta\->embiggen(@_);
\&  }
\&
\&  sub init_meta {
\&      my $package = shift;
\&      my %options = @_;
\&      if (my $meta = Class::MOP::class_of($options{for_class})) {
\&          if ($meta\->isa(\*(AqClass::MOP::Class\*(Aq)) {
\&              my @supers = $meta\->superclasses;
\&              $meta\->superclasses(\*(AqMooseX::Embiggen::Base::Class\*(Aq)
\&                  if @supers == 1 && $supers[0] eq \*(AqMoose::Object\*(Aq;
\&          }
\&      }
\&      $package\->$init_meta(%options);
\&  }
.Ve
.PP
In the previous examples, \f(CW\*(C`init_meta\*(C'\fR was generated for you, but here you must
override it in order to add additional functionality. Some differences to note:
.ie n .IP """build_import_methods"" instead of ""setup_import_methods""" 4
.el .IP "\f(CWbuild_import_methods\fR instead of \f(CWsetup_import_methods\fR" 4
.IX Item "build_import_methods instead of setup_import_methods"
\&\f(CW\*(C`build_import_methods\*(C'\fR simply returns the \f(CW\*(C`import\*(C'\fR, \f(CW\*(C`unimport\*(C'\fR, and
\&\f(CW\*(C`init_meta\*(C'\fR methods, rather than installing them under the appropriate names.
This way, you can write your own methods which wrap the functionality provided
by Moose::Exporter.  The \f(CW\*(C`build_import_methods\*(C'\fR sub also takes an
additional \f(CW\*(C`install\*(C'\fR parameter, which tells it to just go ahead and install
these methods (since we don't need to modify them).
.ie n .IP """sub init_meta""" 4
.el .IP "\f(CWsub init_meta\fR" 4
.IX Item "sub init_meta"
Next, we must write our \f(CW\*(C`init_meta\*(C'\fR wrapper. The important things to remember
are that it is called as a method, and that \f(CW%options\fR needs to be passed
through to the existing implementation. We call the base implementation by
using the \f(CW$init_meta\fR subroutine reference that was returned by
\&\f(CW\*(C`build_import_methods\*(C'\fR earlier.
.IP "Additional implementation" 4
.IX Item "Additional implementation"
This extension sets a different default base object class. To do so, it first
checks to see if it's being applied to a class, and then checks to see if
Moose::Object is that class's only superclass, and if so, replaces that with
the superclass that this extension requires.
.Sp
Note that two extensions that do this same thing will not work together
properly (the second extension to be loaded won't see Moose::Object as the
base object, since it has already been overridden). This is why using a base
object role is recommended for the general case.
.Sp
This \f(CW\*(C`init_meta\*(C'\fR also works defensively, by only applying its functionality if
a metaclass already exists. This makes sure it doesn't break with legacy
extensions which override the metaclass directly (and so must be the first
extension to initialize the metaclass). This is likely not necessary, since
almost no extensions work this way anymore, but just provides an additional
level of protection. The common case of \f(CW\*(C`use Moose; use MooseX::Embiggen;\*(C'\fR
is not affected regardless.
.PP
This is just one example of what can be done with a custom \f(CW\*(C`init_meta\*(C'\fR method.
It can also be used for preventing an extension from being applied to a role,
doing other kinds of validation on the class being applied to, or pretty much
anything that would otherwise be done in an \f(CW\*(C`import\*(C'\fR method.
.SH "LEGACY EXTENSION MECHANISMS"
.IX Header "LEGACY EXTENSION MECHANISMS"
Before the existence of Moose::Exporter and
Moose::Util::MetaRole, there were a number of other ways to extend
Moose. In general, these methods were less cooperative, and only
worked well with a single extension.
.PP
These methods include metaclass.pm, Moose::Policy
(which uses metaclass.pm under the hood), and various
hacks to do what Moose::Exporter does. Please do not use these for
your own extensions.
.PP
Note that if you write a cooperative extension, it should cooperate
with older extensions, though older extensions generally do not
cooperate with each other.
.SH "CONCLUSION"
.IX Header "CONCLUSION"
If you can write your extension as one or more metaclass and base
object roles, please consider doing so. Make sure to read the docs for
Moose::Exporter and Moose::Util::MetaRole as well.
.SH "AUTHORS"
.IX Header "AUTHORS"
.IP "\(bu" 4
Stevan Little <stevan@cpan.org>
.IP "\(bu" 4
Dave Rolsky <autarch@urth.org>
.IP "\(bu" 4
Jesse Luehrs <doy@cpan.org>
.IP "\(bu" 4
Shawn M Moore <sartak@cpan.org>
.IP "\(bu" 4
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
.IP "\(bu" 4
Karen Etheridge <ether@cpan.org>
.IP "\(bu" 4
Florian Ragwitz <rafl@debian.org>
.IP "\(bu" 4
Hans Dieter Pearcey <hdp@cpan.org>
.IP "\(bu" 4
Chris Prather <chris@prather.org>
.IP "\(bu" 4
Matt S Trout <mstrout@cpan.org>
.SH "COPYRIGHT AND LICENSE"
.IX Header "COPYRIGHT AND LICENSE"
This software is copyright (c) 2006 by Infinity Interactive, Inc.
.PP
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

Hry