On Thu, Oct 27, 2005 at 10:19:16PM -0400, Stevan Little wrote:
> I have a question about method conflict resolution works for roles,  
> and I cannot seem to find this in any of the Apoc/Syn documents.
> Here is the basic issue:
> role Foo {
>     method foo { ... }
>     method bar { ... }  # we will use this later :)
> }
> role Bar {
>     method foo { ... }
> }
> role FooBar {
>     does Foo;
>     does Bar;
> }
> Now, at this point we have a method conflict in suspension since  
> (according to A/S-12) method conflicts do not throw an error until a  
> role is composed into a class. This means that when I do this:

If we say that the roles Foo and Bar are composed into the role
FooBar and that method conflicts trigger an exception at composition
time (whether composed into a role or class), then your above
declaration of FooBar will trigger an exception and force the user to
resolve the conflict.

> class MyClass does FooBar {}
> an exception is thrown. Unless of course MyClass has a &foo method,  
> which will disambiguate the conflict. My question then is, can FooBar  
> (the role) disambiguate the &foo conflict?
> role FooBar {
>     does Foo;
>     does Bar;
>     method foo { ... }
> }
> Now, on the surface this seems obvious, of course the FooBar role  
> should be able to disambiguate. 

I agree. Methods declared explicitly in FooBar should trump methods that
have been composed into FooBar (just as it would if FooBar were a class)

> However, when we expand the example  
> other issues show up.
> role Baz {
>     does Foo;
> }
> class MyClass2 does FooBar does Baz {}  # Will this die?

I think yes. FooBar has a method foo() and so does Baz. They may be the
same foo() underneath because that's how the FooBar role decided to
resolve the method conflict, but Baz doesn't know that. Though, the perl
compiler needs to keep track of the composition history of classes/roles
to provide useful error messages.

> Now, since MyClass2 actually does Foo twice, does that mean &bar  
> creates a conflcit? Since &bar would be found through FooBar and Baz.  
> I would think the answer here would be no, and that we would build  
> some kind of unique list of roles so as to avoid repeated consumption  
> like this.

In my world view it doesn't to Foo twice, it does FooBar (which is a
composed of Foo and Bar, but MyClass doesn't know the origin of the
methods) and it does Baz. Since the Baz role and the FooBar role have
the same methods because they were both composed of Foo, the perl
compiler will spit out some messages letting you know that
you've built a class from a doubly composed role.

But if you happen to do

class Foo does Bar does Bar { ... }

perl should be nice enough not to yell at you for doing the Bar role

In the case where really do want the added bits of the Baz role along
with the added bits of the FooBar role (including that disambiguation),
but perl is carping because most of the methods are the same (having
both been composed from Foo), then 1) it's probably a sign that you need
to refactor and 2) you can always use delegation to get the desired
behavior (assuming I'm correct in that you can delegate to specific
roles at composition time as a mechanism for disambiguation).

Jonathan Scott Duff

Reply via email to