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.
Stevan