On Mon, May 31, 2010 at 01:02:26PM -0700, Kate Yoak wrote: > Delegation is a yet another amazing feature of Moose. > > While basic delegation, > > handles => { qw/uri host/ } > > is nice in that it saves some typing and provides nice self-documentation > facility, but not essential. The part that looks so enticing to me is > Role-based delegation: > > does => 'Rain', handles => 'Rain' > > It provides a really elegant aggregation facility. What I found when I tried > this is that only *methods* are delegated - not attributes. > > This brought me to the question of, are attributes that fundamentally > different from methods? I've been using attributes each time I wanted to > skip computation phase on things that wouldn't change, replacing the code > we've typed so many times: > > sub foo{ > my $self = shift; > if ($self->{foo} { return $self->{foo}; } > $self->{foo} = long_and_boring_computation(); > return $self->{foo}; > } > > so much nicer: > > has foo => (is => 'rw', builder => 'long_and_boring_computation', lazy => > 1); > > Now if foo() is part of a role, it'll be applied along with other attributes > & methods. So why does delegation work differently and discriminate against > the poor attributes?
It's a bug, having to do with ordering of role application stuff. Delegation can only delegate methods, but methods generated by attributes in roles currently don't get generated until the role is applied to a class. This is too late for the delegation code to introspect the role to find them. It's someting we're meaning to fix at some point(: As a workaround, you can just define a wrapper method in the role (sub foo { shift->_foo } has foo => (reader => '_foo', ...)). Just defining an empty sub in the role (sub foo {} has foo => (is => 'ro', ...)) seems to work too, but I think that should probably warn, as a parallel to what happens when you do that same thing in a class. -doy