NAME
Moxie - Not Another Moose Clone
VERSION
version 0.02
SYNOPSIS
package Point {
use Moxie;
extends 'Moxie::Object';
has 'x' => sub { 0 };
has 'y' => sub { 0 };
sub x : ro;
sub y : ro;
sub clear ($self) {
@{$self}{'x', 'y'} = (0, 0);
}
}
package Point3D {
use Moxie;
extends 'Point';
has 'z' => sub { 0 };
sub z : ro;
sub clear ($self) {
$self->next::method;
$self->{'z'} = 0;
}
}
DESCRIPTION
Moxie is a reference implemenation for an object system built on top of a set of modules.
- UNIVERSAL::Object
-
This is the suggested base class (through Moxie::Object) for all Moxie classes.
- MOP
-
This provides an API to Classes, Roles, Methods and Slots, which is used by many elements within this module.
- BEGIN::Lift
-
This module is used to create three new keywords;
extends
,with
andhas
. These keywords are executed during compile time and just make calls to the MOP to affect the class being built. - Method::Traits
-
This module is used to handle the method traits which are used mostly for method generation (accessors, predicates, etc.).
- B::CompilerPhase::Hook
-
This allows us to better manipulate the various compiler phases that Perl has.
KEYWORDS
Moxie exports a few keywords using the BEGIN::Lift module described above. These keywords are responsible for setting the correct state in the current package such that it conforms to the expectations of the UNIVERSAL::Object and MOP modules.
All of these keywords are executed during the BEGIN
phase, and the keywords themselves are removed in the UNITCHECK
phase. This prevents them from being mistaken as methods by both perl and the MOP.
extends @superclasses
-
This creates an inheritance relationship between the current class and the classes listed in
@superclasses
.If this is called, Moxie will assume you are a building a class, otherwise it will assume you are building a role. For the most part, you don't need to care about the difference.
This will populate the
@ISA
variable in the current package. with @roles
-
This sets up a role relationship between the current class or role and the roles listed in
@roles
.This will cause Moxie to compose the
@roles
into the current class or role during the nextUNITCHECK
phase.This will populate the
@DOES
variable in the current package. has $name =
sub { $default_value }>-
This creates a new slot in the current class or role, with
$name
being the name of the slot and a subroutine which, when called, returns the$default_value
for that slot.This will populate the
%HAS
variable in the current package.
METHOD TRAITS
It is possible to have Moxie load your Method::Traits providers, this is done when use
ing Moxie like this:
use Moxie traits => [ 'My::Trait::Provider', ... ];
By default Moxie will enable the Moxie::Traits::Provider module to supply this set of traits for use in Moxie classes.
init_args( arg_key =
slot_name, ... )>-
This is a trait that is exclusively applied to the
BUILDARGS
method. This is simply a shortcut to generate aBUILDARGS
method that can map a given constructor parameter to a given slot, this is useful for maintaining encapsulation for things like a private slot with a different public name.# declare a slot with a private name has _bar => sub {}; # map the `foo` key to the `_bar` slot sub BUILDARGS : init_arg( foo => "_bar" );
Using this same trait it is possible to also forbid a constructor parameter from being set, which is done by setting the
slot_name
to beundef
. If thefoo
key is passed to this constructor an exception will be thrown.sub BUILDARGS : init_arg( foo => undef );
ro( ?$slot_name )
-
This will generate a simple read-only accessor for a slot. The
$slot_name
can optionally be specified, otherwise it will use the name of the method the trait is being applied.sub foo : ro; sub foo : ro('_foo');
rw( ?$slot_name )
-
This will generate a simple read-write accessor for a slot. The
$slot_name
can optionally be specified, otherwise it will use the name of the method the trait is being applied.sub foo : rw; sub foo : rw('_foo');
wo( ?$slot_name )
-
This will generate a simple write-only accessor for a slot. The
$slot_name
can optionally be specified, otherwise it will use the name of the method the trait is being applied.sub foo : wo; sub foo : wo('_foo');
predicate( ?$slot_name )
-
This will generate a simple predicate method for a slot. The
$slot_name
can optionally be specified, otherwise it will use the name of the method the trait is being applied.sub foo : predicate; sub foo : predicate('_foo');
clearer( ?$slot_name )
-
This will generate a simple clearing method for a slot. The
$slot_name
can optionally be specified, otherwise it will use the name of the method the trait is being applied.sub foo : clearer; sub foo : clearer('_foo');
handles( $slot_name-
$delegate_method )>-
This will generate a simple delegate method for a slot. The
$slot_name
and$delegate_method
, seperated by an arrow (->
), must be specified or an exception is thrown.sub foobar : handles('foo->bar');
No attempt will be made to verify that the value stored in
$slot_name
is an object, or that it responds to the$delegate_method
specified, this is the responsibility of the writer of the class. private( ?$slot_name )
-
This will generate a private read-write accessor for a slot. The
$slot_name
can optionally be specified, otherwise it will use the name of the method the trait is being applied.my sub foo : private; my sub foo : private('_foo');
The privacy is accomplished via the use of a lexical method, this means that the method is not availble outside of the package scope and is not available to participate in method dispatch, however it does know the current invocant, so there is no need to pass that in. This results in code that looks like this:
sub my_method ($self, @stuff) { # simple access ... my $foo = foo(); # passing to other methods ... $self->do_something_with_foo( foo() ); # calling methods on an embedded object ... foo()->call_method_on_foo(); }
This feature is considered experimental, but then again, so is this whole module, so I guess you can safely ignore that then.
FEATURES ENABLED
This module enabled a number of features in Perl which are currently considered experimental, see the experimental module for more information.
signatures
postderef
postderef_qq
current_sub
lexical_subs
say
state
refaliasing
PRAGMAS ENABLED
We enabled both the strict and warnings pragmas, but we disable the reserved
warning so that we can use lowercase CODE attributes with Method::Traits.
AUTHOR
Stevan Little <stevan@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2017 by Stevan Little.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.