X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FRole%2FTiny.pm;h=07fb3d44cbde003db625eb13f2434ae3d8a7b972;hb=cca4fd3e2b7ba5b6b6bd615d4f46ae2aefffd27b;hp=9badeefb345ccb761c3b5f84a6b3e20c11119992;hpb=1133b2a96e2d667b84f5df7987c95a5771481e70;p=gitmo%2FRole-Tiny.git diff --git a/lib/Role/Tiny.pm b/lib/Role/Tiny.pm index 9badeef..07fb3d4 100644 --- a/lib/Role/Tiny.pm +++ b/lib/Role/Tiny.pm @@ -6,18 +6,20 @@ sub _getstash { \%{"$_[0]::"} } use strict; use warnings FATAL => 'all'; -our $VERSION = '1.003002'; # 1.3.2 +our $VERSION = '1.003002'; $VERSION = eval $VERSION; our %INFO; our %APPLIED_TO; our %COMPOSED; our %COMPOSITE_INFO; +our @ON_ROLE_CREATE; # Module state workaround totally stolen from Zefram's Module::Runtime. BEGIN { *_WORK_AROUND_BROKEN_MODULE_STATE = "$]" < 5.009 ? sub(){1} : sub(){0}; + *_MRO_MODULE = "$]" < 5.010 ? sub(){"MRO/Compat.pm"} : sub(){"mro.pm"}; } sub Role::Tiny::__GUARD__::DESTROY { @@ -71,6 +73,7 @@ sub import { @{$INFO{$target}{not_methods}={}}{@not_methods} = @not_methods; # a role does itself $APPLIED_TO{$target} = { $target => undef }; + $_->($target) for @ON_ROLE_CREATE; } sub role_application_steps { @@ -100,8 +103,9 @@ sub apply_roles_to_object { my ($me, $object, @roles) = @_; die "No roles supplied!" unless @roles; my $class = ref($object); - bless($object, $me->create_class_with_roles($class, @roles)); - $object; + # on perl < 5.8.9, magic isn't copied to all ref copies. bless the parameter + # directly, so at least the variable passed to us will get any magic applied + bless($_[1], $me->create_class_with_roles($class, @roles)); } my $role_suffix = 'A000'; @@ -142,16 +146,12 @@ sub create_class_with_roles { die "${role} is not a Role::Tiny" unless $me->is_role($role); } - if ($] >= 5.010) { - require mro; - } else { - require MRO::Compat; - } + require(_MRO_MODULE); my $composite_info = $me->_composite_info_for(@roles); my %conflicts = %{$composite_info->{conflicts}}; if (keys %conflicts) { - my $fail = + my $fail = join "\n", map { "Method name conflict for '$_' between roles " @@ -202,7 +202,7 @@ sub apply_roles_to_package { delete @conflicts{@have}; if (keys %conflicts) { - my $fail = + my $fail = join "\n", map { "Due to a method name conflict between roles " @@ -361,7 +361,21 @@ sub _install_methods { foreach my $i (grep !exists $has_methods{$_}, keys %$methods) { no warnings 'once'; - *{_getglob "${to}::${i}"} = $methods->{$i}; + my $glob = _getglob "${to}::${i}"; + *$glob = $methods->{$i}; + + # overloads using method names have the method stored in the scalar slot + # and &overload::nil in the code slot. + next + unless $i =~ /^\(/ + && defined &overload::nil + && $methods->{$i} == \&overload::nil; + + my $overload = ${ *{_getglob "${role}::${i}"}{SCALAR} }; + next + unless defined $overload; + + *$glob = \$overload; } $me->_install_does($to); @@ -417,11 +431,7 @@ sub _install_does { sub does_role { my ($proto, $role) = @_; - if ($] >= 5.010) { - require mro; - } else { - require MRO::Compat; - } + require(_MRO_MODULE); foreach my $class (@{mro::get_linear_isa(ref($proto)||$proto)}) { return 1 if exists $APPLIED_TO{$class}{$role}; } @@ -434,6 +444,7 @@ sub is_role { } 1; +__END__ =encoding utf-8 @@ -519,7 +530,7 @@ Declares a list of methods that must be defined to compose role. Composes another role into the current role (or class via L). If you have conflicts and want to resolve them in favour of Some::Role1 you -can instead write: +can instead write: with 'Some::Role1'; with 'Some::Role2'; @@ -625,17 +636,22 @@ New class is returned. Returns true if the given package is a role. +=head1 CAVEATS + +=over 4 + +=item * On perl 5.8.8 and earlier, applying a role to an object won't apply any +overloads from the role to all copies of the object. + +=back + =head1 SEE ALSO L is the attribute-less subset of L; L is a meta-protocol-less subset of the king of role systems, L. -If you don't want method modifiers and do want to be forcibly restricted -to a single role application per class, Ovid's L exists. But -Stevan Little (the L author) and I don't find the additional -restrictions to be amazingly helpful in most cases; L's choices -are more a guide to what you should prefer doing, to our mind, rather than -something that needs to be enforced. +Ovid's L provides roles with a similar scope, but without method +modifiers, and having some extra usage restrictions. =head1 AUTHOR