On Oct 28, 2005, at 3:45 PM, Rob Kinyon wrote:
Doing it any other way leads to the following: if A does rA and B isa
A and B defines an attribute that conflicts with the one provided by
rA, how on earth is that supposed to be detected? Especially given
that the inheritance tree of a class can be modified at runtime.

B should not know or care that A does rA, because by the time B gets to A, rA has already been consumed by A.

If B does not want it's attributes to conflict,.. make 'em private. If rA is concerned that it's attributes will get mussed with, it should make 'em private too (which IMO would mean that A gets a new private attribute, not that it is privatet to the role).

Your method (as we have discussed in the past) means that Roles now have instance specific data, which needs to be stored somewhere, somehow (not too difficult). And our class now needs to keep information about the roles it composed around so that it can dispatch to methods appropriately (also not too bad). This then means that the method dispatcher, when it cannot find a private method locally, needs to check all the roles which were composed into the class to find the correct private method and then call that method (I assuming no method conflicts here, but they can (and will) happen). The method then needs to be able to find and extract the role specific private instance data (this action itself requires some complex access control checks), and then do something with it.

Like I said, this is assuming we have no conflicts, because the dispatcher will have a hard time determining which role specific private method named &:foo you mean in the context this is all happening in. And if we check for conflicts up front, we start to run into the same issues that we did before.

One possible solution might be to only allow methods defined within the role to access the private role methods. But then what happens if that method is in conflict. Here is an example:

role Foo {
    has $:bar; # this is role private data
    method :get_bar { $:bar } # a role private method

method gimme_bar { self.:get_bar() } # the public face to the private role data

class Blah does Foo {
    method gimme_bar { ... }

At this point :get_bar and $:bar are totally inaccessible.

IMO, roles should be just containers, and they should hand over everything they have to the class they are composed into. I also think Subclasses should not care what roles their superclasses consumed, that is personal information for the class only to know.


Reply via email to