Hi,
I liked better the fact that roles could change behavior in the consumer
class - thus provide a much cleaner interface (less coupling).
In the abilities suggestion, attach subroutine must take into account in
its code all the possible abilities.
Consider the following roles:
package Abilities::Strong;
use Moose::Role;
with 'Abilities::Base';
after attack => sub {
my ($self, $enemy) = @_;
$enemy->lose_life(2);
};
package Abilities::Undead;
use Moose::Role;
use Moose::Util qw/apply_all_roles/;
with 'Abilities::Base';
after 'attack' => sub {
my ($self, $enemy) = @_;
apply_all_roles($enemy, 'Abilities::Undead');
};
That scheme allows more flexibility in coding new abilities as plugins
later on.
(working code at: https://gist.github.com/1791637)
On 10 February 2012 18:52, Nick Perez <[email protected]> wrote:
> On Fri, 10 Feb 2012 18:07:58 +0200
> ynon perek <[email protected]> wrote:
>
> > Is it also possible to remove a role from an instance ?
>
> While it would seemingly make sense to (ab)use the roles/traits system
> for something like this, it probably is a better idea to have an
> attribute that contains a list of abilities that the instance could use
> to determine its actions.
>
> has abilities => (
> is => 'ro',
> traits => [qw/Hash/],
> isa => 'HashRef',
> default => sub { +{} },
> handles => {
> has_ability => 'exists',
> get_ability => 'get',
> set_ability => 'set',
> }
> );
>
> ...
>
> sub deal_damage {
> my ($self) = @_;
> return $self->base_damage + ($self->has_ability('Strong') ?
> $self->get_ability : 0);
> }
>
> # attack
> $badguy->set_ability('Strong' => 5);
>
> $target->receive_damage($badguy->deal_damage);
>
>
> Doing it this way also makes it easier to serialize (like making save
> file).
>
>
> --
>
> Nicholas Perez
> XMPP/Email: [email protected]
> http://search.cpan.org/~nperez/
> http://github.com/nperez
>