If you can't read please download the document
Upload
xsawyer
View
6.943
Download
1
Embed Size (px)
Citation preview
Moose
A postmodernmetaclass-basedobject systemfor Perl 5
Objects in Perl 5
(a short intro)
A blessed hashref
Manual new() method
No real attributes
bless {}, __PACKAGE__;
sub new {my ( $class, @args ) = @_;
my $self = { @args }; # paramsbless $self, $class;return $self;}
sub name {my ( $self, $name ) = @_;$name and$self->{'name'} = $name;
return $self->{'name'};}
Why would you want to use Moose?
Moose
package Person;
use strict;use warnings;
use Carp qw( confess );use DateTime;use DateTime::Format::Natural;
sub new { my $class = shift; my %p = ref $_[0] ? %{ $_[0] } : @_;
exists $p{name} or confess 'name is a required attribute'; $class->_validate_name( $p{name} );
exists $p{birth_date} or confess 'birth_date is a required attribute';
$p{birth_date} = $class->_coerce_birth_date( $p{birth_date} ); $class->_validate_birth_date( $p{birth_date} );
$p{shirt_size} = 'l' unless exists $p{shirt_size}:
$class->_validate_shirt_size( $p{shirt_size} );
return bless \%p, $class;}
sub _validate_name { shift; my $name = shift;
local $Carp::CarpLevel = $Carp::CarpLevel + 1;
defined $name or confess 'name must be a string';}
Plain old Perl 5
package User;
use Email::Valid;use Moose;use Moose::Util::TypeConstraints;
extends 'Person';
subtype 'Email' => as 'Str' => where { Email::Valid->address($_) } => message { "$_ is not a valid email address" };
has email_address => ( is => 'rw', isa => 'Email', required => 1,);
Get it?
Defining an object in Moose
use strict
use warnings
An object!
new() method
A pon-.. err.. a moose!
package User;
use Moose;
1;
You get:
Full-Affordance accessors
'ro' is also available for read-only attributes!
You can set the getter or setter manually via reader/writer
I'll show more attribute options later on
has name => (is => 'rw',);
An attribute with type constraint
Lots of types: Str, Int, ArrayRef, HashRef, CodeRef, Regexp
You can combine: ArrayRef[Str], HashRef[ArrayRef[Int]]
They have inheritance: Int is a Num
Roll your own using subtype
package User;
use Moose;
has name => (is => 'rw',isa => 'Str',);
1;
Methods are the same as before
sub method {my $self = shift;
...
$self->more();}
Inheritance is as easy as...
Multiple inheritance is also possible, extends accepts an array
package Punk;
use Moose;extends 'Person';
1;
package Child;
use Moose;
extends qw/ Father Mother /;
1;
Roles are even easier!
Multiple roles are recommend! with accepts an array too
package Punk;
use Moose;extends 'Person';with 'Piercings';
1;
package Punk;
use Moose;extends 'Person';
with qw/PiercingsTattoos/;
1;
More hooks than a coat rack!
package User::Secure;
use Moose;extends 'User';
before login => sub {my $self = shift;$self->security_check();};
1;
before
after
around
inner
augment
Back to attributes options...
has set => (is => 'rw',isa => 'Set::Object',default => sub { Set::Object->new },required => 1,lazy => 1,predicate => 'has_set', clearer => 'clear_set',builder => 'build_set',);
Attribute options
default => 'kitteh', # stringdefault => 3, # numberdefault => sub { {} }, # HashRefdefault => sub { [] }, # ArrayRefdefault => sub { Object->new }, # an Object
etc. etc.
(if you need a more elaborate sub, use builder)
default
Attribute options
required => 1, # requiredrequired => 0, # not required
required
Attribute options
lazy => 1, # make it lazy
Class will not create the slot for this attribute unless it absolutely has to. That is defined by whether it is accessed at all.
Wasn't accessed? You don't pay the penalty! :)
lazy = good
lazy
Attribute options
builder => 'build_it', # subroutine name
sub build_it {my $self = shift; # not a problem!return Some::Object->new($self->more_opts,);}
# and, obviously...after build_it => sub { they will come };
(a builder sets the value of the attribute)
builder
Attribute options
clearer => 'clear_it', # subroutine name
# you don't need to create the subroutinesub time_machine {my $self = shift;$self->clear_it; # 'it' never happened :)}
(a clearer clears the attribute, not just the value)
clearer
Attribute options
predicate => 'has_it', # subroutine name
# you don't need to create the subroutinesub try_to_do_it {my $self = shift;$self->has_it && $self->do_it();}
(a predicate checks an attribute exists)(even false values)(which is good!)
predicate
Attribute options
lazy_build => 1, # 1,builder => '_build_it', # privateclearer => 'clear_it',predicate => 'has_it',
(lazy_build is recommended)
lazy_build
Moose
It's beautiful
It's clean
It's stable
It's here to stay
Check it out!
A ton more options
More control
Roles / Traits