>From memory, consume the interface/interface-role after all other
declarations and role consumption, e.g.

I get that. Here's an example:

package FooRole;
use Moose::Role;

requires qw(open close read write);

requires qw(eenie meenie);

#----------------------------------------------

package FooWrapper;
use Moose;

has delegate => (
    is => 'ro',
    isa => 'Foo',
    handles => [ qw(open close read write) ],
    required => 1,
);

sub eenie {...}
sub meenie {...}

with qw(FooRole);

That only works if the with comes after the delegation has been
established. The trouble is, I only want to write that list qw(open close
read write) once. I could put that in say, @FooRole::METHODS_TO_DELEGATE.
But
that variable probably won't be available to me until *after* FooRole has
been loaded by the with. At that point, it is too late, and it won't
compile because the class hasn't satisfied the role.

The workaround would be to explicitly require FooRole; before defining the
delegate attribute. That way I can ensure @FooRole::METHODS_TO_DELEGATE is
available at the right time. But that is a hack.

You could argue that I shouldn't do this at all, because FooRole shouldn't
know anything about how the required methods will be implemented. And if I
really want to commit to a particular implementation (like using the
delegate to handle qw(open close read write) for example) then I should
just put that in the role directly.

That last argument does make sense to me, which is also why I'm leaning
towards abstract base classes again. In this situation, the interface is
for a hierarchy of related classes and I have some feelings about a default
implementation (i.e. the delegation part). It the interface were for
unrelated classes and I had no ideas about the implementation, then a role
would make more sense.

-Jeff

Reply via email to