X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoo.pm;h=f188c1259ed7bfdb7ba1352435d8b889ba0e6e52;hb=b682218c3bf8133f99d55af4b58e7698e58a4fcd;hp=28e91a87e23d73d15e7537ade3e363e6a20bfce7;hpb=2e575bcd0d464b776bedd3731903a2f6a1ffb892;p=gitmo%2FRole-Tiny.git diff --git a/lib/Moo.pm b/lib/Moo.pm index 28e91a8..f188c12 100644 --- a/lib/Moo.pm +++ b/lib/Moo.pm @@ -2,8 +2,9 @@ package Moo; use strictures 1; use Moo::_Utils; +use B 'perlstring'; -our $VERSION = '0.009001'; # 0.9.1 +our $VERSION = '0.009013'; # 0.9.13 $VERSION = eval $VERSION; our %MAKERS; @@ -15,18 +16,19 @@ sub import { return if $MAKERS{$target}; # already exported into this package *{_getglob("${target}::extends")} = sub { _load_module($_) for @_; - *{_getglob("${target}::ISA")} = \@_; + # Can't do *{...} = \@_ or 5.10.0's mro.pm stops seeing @ISA + @{*{_getglob("${target}::ISA")}{ARRAY}} = @_; }; *{_getglob("${target}::with")} = sub { - require Moo::Role; + { local $@; require Moo::Role; } die "Only one role supported at a time by with" if @_ > 1; - Moo::Role->apply_role_to_package($_[0], $target); + Moo::Role->apply_role_to_package($target, $_[0]); }; $MAKERS{$target} = {}; *{_getglob("${target}::has")} = sub { my ($name, %spec) = @_; ($MAKERS{$target}{accessor} ||= do { - require Method::Generate::Accessor; + { local $@; require Method::Generate::Accessor; } Method::Generate::Accessor->new })->generate_method($target, $name, \%spec); $class->_constructor_maker_for($target) @@ -34,51 +36,74 @@ sub import { }; foreach my $type (qw(before after around)) { *{_getglob "${target}::${type}"} = sub { - require Class::Method::Modifiers; + { local $@; require Class::Method::Modifiers; } _install_modifier($target, $type, @_); }; } { no strict 'refs'; @{"${target}::ISA"} = do { - require Moo::Object; ('Moo::Object'); + { local $@; require Moo::Object; } ('Moo::Object'); } unless @{"${target}::ISA"}; } } sub _constructor_maker_for { - my ($class, $target) = @_; + my ($class, $target, $select_super) = @_; return unless $MAKERS{$target}; $MAKERS{$target}{constructor} ||= do { - require Method::Generate::Constructor; + { + local $@; + require Method::Generate::Constructor; + require Sub::Defer; + } + my ($moo_constructor, $con); + + if ($select_super && $MAKERS{$select_super}) { + $moo_constructor = 1; + $con = $MAKERS{$select_super}{constructor}; + } else { + my $t_new = $target->can('new'); + if ($t_new) { + if ($t_new == Moo::Object->can('new')) { + $moo_constructor = 1; + } elsif (my $defer_target = (Sub::Defer::defer_info($t_new)||[])->[0]) { + my ($pkg) = ($defer_target =~ /^(.*)::[^:]+$/); + if ($MAKERS{$pkg}) { + $moo_constructor = 1; + $con = $MAKERS{$pkg}{constructor}; + } + } + } else { + $moo_constructor = 1; # no other constructor, make a Moo one + } + }; Method::Generate::Constructor ->new( package => $target, accessor_generator => do { - require Method::Generate::Accessor; + { local $@; require Method::Generate::Accessor; } Method::Generate::Accessor->new; - } + }, + construction_string => ( + $moo_constructor + ? ($con ? $con->construction_string : undef) + : ('$class->'.$target.'::SUPER::new(@_)') + ), + subconstructor_generator => ( + $class.'->_constructor_maker_for($class,'.perlstring($target).')' + ), ) ->install_delayed - ->register_attribute_specs(do { - my @spec; - # using the -last- entry in @ISA means that classes created by - # Role::Tiny as N roles + superclass will still get the attributes - # from the superclass - if (my $super = do { no strict 'refs'; ${"${target}::ISA"}[-1] }) { - if (my $con = $MAKERS{$super}{constructor}) { - @spec = %{$con->all_attribute_specs}; - } - } - @spec; - }); + ->register_attribute_specs(%{$con?$con->all_attribute_specs:{}}) } } 1; - =pod +=encoding utf-8 + =head1 NAME Moo - Minimalist Object Orientation (with Moose compatiblity) @@ -137,6 +162,26 @@ thirds of L. Unlike C this module does not aim at full L compatibility. See L for more details. +=head1 WHY MOO EXISTS + +If you want a full object system with a rich Metaprotocol, L is +already wonderful. + +I've tried several times to use L but it's 3x the size of Moo and +takes longer to load than most of my Moo based CGI scripts take to run. + +If you don't want L, you don't want "less metaprotocol" like L, +you want "as little as possible" - which means "no metaprotocol", which is +what Moo provides. + +By Moo 1.0 I intend to have Moo's equivalent of L built in - +if Moose gets loaded, any Moo class or role will act as a Moose equivalent +if treated as such. + +Hence - Moo exists as its name - Minimal Object Orientation - with a pledge +to make it smooth to upgrade to L when you need more than minimal +features. + =head1 IMPORTED METHODS =head2 new @@ -149,14 +194,43 @@ or =head2 BUILDARGS -This feature from Moose is not yet supported. + around BUILDARGS => sub { + my $orig = shift; + my ( $class, @args ) = @_; + + unshift @args, "attr1" if @args % 2 == 1; + + return $class->$orig(@args); + }; -=head2 BUILDALL + Foo::Bar->new( 3 ); -Don't override (or probably even call) this method. Instead, you can define -a C method on your class and the constructor will automatically call the -C method from parent down to child after the object has been -instantiated. Typically this is used for object validation or possibly logging. +The default implementation of this method accepts a hash or hash reference of +named parameters. If it receives a single argument that isn't a hash reference +it throws an error. + +You can override this method in your class to handle other types of options +passed to the constructor. + +This method should always return a hash reference of named options. + +=head2 BUILD + +Define a C method on your class and the constructor will automatically +call the C method from parent down to child after the object has +been instantiated. Typically this is used for object validation or possibly +logging. + +=head2 DEMOLISH + +If you have a C method anywhere in your inheritance hierarchy, +a C method is created on first object construction which will call +C<< $instance->DEMOLISH($in_global_destruction) >> for each C +method from child upwards to parents. + +Note that the C method is created on first construction of an object +of your class in order to not add overhead to classes without C +methods; this may prove slightly surprising if you try and define your own. =head2 does @@ -201,7 +275,7 @@ The options for C are as follows: =item * is B, must be C or C. Unsurprisingly, C generates an -accessor that will not respond to arguments; to be clear: a setter only. C +accessor that will not respond to arguments; to be clear: a getter only. C will create a perlish getter/setter. =item * isa @@ -218,10 +292,6 @@ L =item * coerce -This Moose feature is not yet supported - -=begin hide - Takes a coderef which is meant to coerce the attribute. The basic idea is to do something like the following: @@ -229,9 +299,28 @@ do something like the following: $_[0] + 1 unless $_[0] % 2 }, +Coerce does not require C to be defined. + L -=end hide +=item * handles + +Takes a string + + handles => 'RobotRole' + +Where C is a role (L) that defines an interface which +becomes the list of methods to handle. + +Takes a list of methods + + handles => [ qw( one two ) ] + +Takes a hashref + + handles => { + un => 'one', + } =item * trigger @@ -288,6 +377,18 @@ another attribute to be set. B. Set this if the attribute must be passed on instantiation. +=item * reader + +The value of this attribute will be the name of the method to get the value of +the attribute. If you like Java style methods, you might set this to +C + +=item * writer + +The value of this attribute will be the name of the method to set the value of +the attribute. If you like Java style methods, you might set this to +C + =item * weak_ref B. Set this if you want the reference that the attribute contains to @@ -358,3 +459,58 @@ manually set all the options it implies. C is not supported since the author considers it a bad idea. C is not supported since it's a very poor replacement for POD. + +Handling of warnings: when you C we enable FATAL warnings. The nearest +similar invocation for L would be: + + use Moose; + use warnings FATAL => "all"; + +Additionally, L supports a set of attribute option shortcuts intended to +reduce common boilerplate. The set of shortcuts is the same as in the L +module L. So if you: + + package MyClass; + use Moo; + +The nearest L invocation would be: + + package MyClass; + + use Moose; + use warnings FATAL => "all"; + use MooseX::AttributeShortcuts; + +=head1 AUTHOR + +mst - Matt S. Trout (cpan:MSTROUT) + +=head1 CONTRIBUTORS + +dg - David Leadbeater (cpan:DGL) + +frew - Arthur Axel "fREW" Schmidt (cpan:FREW) + +hobbs - Andrew Rodland (cpan:ARODLAND) + +jnap - John Napiorkowski (cpan:JJNAPIORK) + +ribasushi - Peter Rabbitson (cpan:RIBASUSHI) + +chip - Chip Salzenberg (cpan:CHIPS) + +ajgb - Alex J. G. Burzyński (cpan:AJGB) + +doy - Jesse Luehrs (cpan:DOY) + +=head1 COPYRIGHT + +Copyright (c) 2010-2011 the Moo L and L +as listed above. + +=head1 LICENSE + +This library is free software and may be distributed under the same terms +as perl itself. + +=cut