Moose and Moo
29.1 Moo (Lightweight, Fast Startup)
package Point;
use Moo;
use Types::Standard qw(Num Str ArrayRef);
use namespace::clean;
has x => (is => 'ro', isa => Num, default => 0);
has y => (is => 'ro', isa => Num, default => 0);
has label => (is => 'rw', isa => Str, predicate => 1, clearer => 1);
has history => (is => 'lazy', isa => ArrayRef);
sub _build_history { [] } # lazy builder
sub BUILD { # runs after construction
my ($self, $args) = @_;
die "x must be >= 0" if $self->x < 0;
}
sub to_string {
my $self = shift;
return sprintf '(%s, %s)', $self->x, $self->y;
}
package Point3D;
use Moo;
extends 'Point';
has z => (is => 'ro', default => 0);
around to_string => sub { # method modifiers: before, after, around
my ($orig, $self, @args) = @_;
my $s = $self->$orig(@args);
$s =~ s/\)$/, ${\ $self->z })/;
return $s;
};
package main;
my $p = Point3D->new(x => 1, y => 2, z => 3);
say $p->to_string; # (1, 2, 3)
$p->label('origin-ish');
say $p->has_label ? 'labeled' : 'no label';29.2 Moose (Full-Featured, Introspective)
Mouse / Object::Pad / Core class Minimal (upgrades to Moose if needed) Via Type::Tiny Role::Tiny / Moo::Role Role::Tiny / built in (Object::Pad) Large apps needing introspection Default choice for most CPAN/apps Object::Pad/core class for new code
Type::Tiny works with Moo, Moose, Mouse, and plain subs (Types::Standard, Types::Common::Numeric).
Other systems: Mojo::Base (minimal, used in Mojolicious), Class::Accessor, Class::Tiny, Object::Pad (the testbed for the core class feature).
package BankAccount;
use Moose;
use Moose::Util::TypeConstraints;
use namespace::autoclean;
subtype 'PositiveNum', as 'Num', where { $_ > 0 }, message { "Amount must be positive" };
has owner => (is => 'ro', isa => 'Str', required => 1);
has balance => (is => 'ro', isa => 'Num', default => 0, writer => '_set_balance');
has transactions => (
traits => ['Array'],
is => 'ro',
isa => 'ArrayRef[HashRef]',
default => sub { [] },
handles => { add_transaction => 'push', transaction_count => 'count' }, # native traits
);
sub deposit {
my ($self, $amount) = @_;
find_type_constraint('PositiveNum')->assert_valid($amount);
$self->_set_balance($self->balance + $amount);
$self->add_transaction({ type => 'deposit', amount => $amount });
}
__PACKAGE__->meta->make_immutable; # speed optimization
1;