Em Sex, 2009-07-10 às 15:39 -0700, Jon Lang escreveu:
> The key to understanding roles is to note that roles don't implement
> methods; classes implement methods.

Er, while I see your point, Roles are not just interfaces... they are OO
components that can be plugged into other classes. They often are used
for type identity exactly because of that attribute, since you won't be
enforcing any hierarchy.

> Roles define which methods must be implemented, and suggest ways that
> they might be implemented; classes decide which implementation to use.
> Anything that breaks this paradigm is a Bad Thing.

That's not the common conception in Roles usage, specially in Moose. As
I said, Roles are not just interfaces, they are OO reuseable components.
The spec itself says:

        Classes are primarily for instance management, not code reuse.
        Consider using C<roles> when you simply want to factor out
        common code.

The key issue here is Perl 6 wasn't yet used to the extent that
Moose::Roles are, and Moose people have identified that the use of Roles
as reusable components raised the issue when the class inadvertedly
overrides one of the methods that are implemented by one of the composed
roles.

I did think that this should be the expected behavior, but when the
people that is heavily using it says "it took me a lot of time to
debug", it indicates that there's something wrong with the behavior.

So now I changed my mind, inheritance is about overriding behavior, so
when you implement a method in the subclass it is a natural thinking
that this should override the superclass, but when you think about it
really carefully this logic doesn't really map well to Roles
(considering roles as OO reuseable components).

That being said, I'd think the following as an interesting solution:

 role R1 {
   method foo() {...} # degenerates to interface
 }
 role R2 does R1 {
   method bar() {
     # some implementation
   }
   method baz() {
     # some implementation
   }
 }

 class Bla does R2 {
   method foo {
     # implementing here is natural, since the role only
     # declared a stub, it's even a warning not to implement it
   }
   supersede method bar  {
     # explicitly tells that I want to ignore the implementation
     # in the role. nextsame wouldn't find the role implementation.
   }
   augment method baz {
     # explicitly tells that I want to provide an additional
     # implementation besides the one in the role. nextsame would find
     # the role implementation.
   }
 }

In the above example, declaring a method without either "supersede" or
"augment" would result in a compile-time warning, while using "augment"
semantics by default.

dainel

Reply via email to