Sub::HandlesVia allows you to delegate methods from your class to the values of your objects' attributes.
Conceptually, it allows you to define "$object->push_number($n)" to be a shortcut for
"$object->numbers->push($n)" except that "$object->numbers" is an arrayref, so doesn't have methods you
can call on it like "push".
For Moose and Mouse, Sub::HandlesVia can use their metaobject protocols to grab an attribute's definition
and install the methods it needs to. For Moo, it can wrap "has" and do its stuff that way. For other
classes, you need to be more explicit and tell it what methods to delegate to what attributes.
package Kitchen {
# constructor
sub new {
my ( $class, %arg ) = @_;
$arg{food} ||= [];
return bless( \%arg, $class );
}
# getter/setter for `food`
sub food {
(@_ == 1) ? $_[0]{food} : ( $_[0]{food} = $_[1] );
}
use Sub::HandlesVia qw( delegations );
delegations(
attribute => 'food'
handles_via => 'Array',
handles => {
'add_food' => 'push',
'find_food' => 'grep',
},
);
}
Setting "attribute" to "food" means that when Sub::HandlesVia needs to get the food list, it will call
"$kitchen->food" and when it needs to set the food list, it will call "$kitchen->food($value)". If you
have separate getter and setter methods, just do:
attribute => [ 'get_food', 'set_food' ],
Or if you don't have any accessors and want Sub::HandlesVia to directly access the underlying hashref:
attribute => '{food}',
Or maybe you have a setter, but want to use hashref access for the getter:
attribute => [ '{food}', 'set_food' ],
Or maybe you still want direct access for the getter, but your object is a blessed arrayref instead of a
blessed hashref:
attribute => [ '[7]', 'set_food' ],
Or maybe your needs are crazy unique:
attribute => [ \&getter, \&setter ],
The coderefs are passed the instance as their first argument, and the setter is also passed a value to
set.
Really, I don't think there's any object system that this won't work for!
If you supply an arrayref with a getter and setter, it's also possible to supply a third argument which
is a coderef or string which will be called as a method if needing to "reset" the value. This can be
thought of like a default or builder.
(The "delegations" function can be imported into Moo/Mouse/Moose classes too, in which case the
"attribute" needs to be the same attribute name you passed to "has". You cannot use a arrayref, coderef,
hash key, or array index.)