From: Toby Inkster Date: Fri, 19 Oct 2012 13:52:44 +0000 (+0100) Subject: implementations for DOES and around does => sub {...} X-Git-Tag: v1.002000~2 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=fa89d58252a80231301b8c7f05ec5a8e21991d68;p=gitmo%2FRole-Tiny.git implementations for DOES and around does => sub {...} --- diff --git a/Changes b/Changes index 713988d..9dd6188 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,7 @@ - load class in addition to roles when using create_class_from_roles - fix module name in Makefile.PL (RT#78591) + - when classes consume roles, override their DOES method (RT#79747) + - method modifiers can be used for 'does' and 'DOES' 1.001005 - 2012-07-18 - localize UNIVERSAL::can change to avoid confusing TB2 diff --git a/lib/Role/Tiny.pm b/lib/Role/Tiny.pm index 609f4a6..07ea94a 100644 --- a/lib/Role/Tiny.pm +++ b/lib/Role/Tiny.pm @@ -86,11 +86,6 @@ sub apply_single_role_to_package { $me->_install_modifiers($to, $info->{modifiers}); - # only add does() method to classes and only if they don't have one - if (not $INFO{$to} and not $to->can('does')) { - *{_getglob "${to}::does"} = \&does_role; - } - # copy our role list into the target's @{$APPLIED_TO{$to}||={}}{keys %{$APPLIED_TO{$role}}} = (); } @@ -157,8 +152,6 @@ sub create_class_with_roles { do { my %h; @h{map @{$_->{requires}||[]}, @info} = (); keys %h } ); - *{_getglob "${new_name}::does"} = \&does_role unless $new_name->can('does'); - @{$APPLIED_TO{$new_name}||={}}{ map keys %{$APPLIED_TO{$_}}, @roles } = (); @@ -298,6 +291,8 @@ sub _install_methods { no warnings 'once'; *{_getglob "${to}::${i}"} = $methods->{$i}; } + + $me->_install_does($to); } sub _install_modifiers { @@ -316,6 +311,27 @@ sub _install_single_modifier { Class::Method::Modifiers::install_modifier(@args); } +my $FALLBACK = sub { 0 }; +sub _install_does { + my ($me, $to) = @_; + + # only add does() method to classes + return if $INFO{$to}; + + # add does() only if they don't have one + *{_getglob "${to}::does"} = \&does_role unless $to->can('does'); + + return if ($to->can('DOES') and $to->can('DOES') != UNIVERSAL->can('DOES')); + + my $existing = $to->can('DOES') || $to->can('isa') || $FALLBACK; + my $new_sub = sub { + my ($proto, $role) = @_; + Role::Tiny::does_role($proto, $role) or $proto->$existing($role); + }; + no warnings 'redefine'; + *{_getglob "${to}::DOES"} = $new_sub; +} + sub does_role { my ($proto, $role) = @_; if ($] >= 5.010) { @@ -474,7 +490,11 @@ composed into unless that class already has an ->does method, so ... } -will work for classes but to test a role, one must use ::does_role directly +will work for classes but to test a role, one must use ::does_role directly. + +Additionally, Role::Tiny will override the standard Perl C method +for your class. However, if C class in your class' inheritance +heirarchy provides C, then Role::Tiny will not override it. =head1 METHODS @@ -540,6 +560,8 @@ Mithaldu - Christian Walde (cpan:MITHALDU) ilmari - Dagfinn Ilmari Mannsåker (cpan:ILMARI) +tobyink - Toby Inkster (cpan:TOBYINK) + =head1 COPYRIGHT Copyright (c) 2010-2012 the Role::Tiny L and L