On Fri, Apr 23, 2004 at 03:34:32PM -0700, Jonathan Lang wrote:
: Larry Wall wrote:
: > On Fri, Apr 23, 2004 at 02:37:58PM -0700, Jonathan Lang wrote:
: > : Note that the problem extends past accessors: a role's methods can
: > : access its attributes directly.  So:
: > : 
: > :   role A {has Cat $.x; method m1 {return $.x;};}
: > :   role B {has Dog $.x; method m2 {return $.x;};}
: > :   class Foo {does Cat; does Dog;}
: > :   my Foo $bar;
: > :   $bar.m1;     # returns $A::x, right?
: > :   $bar.m2;     # returns $B::x, right?
: > : 
: > : If the two $.x's are completely equivelent, you end up with redundant
: > : data storage.  
: > 
: > Actually, it'd blow up at composition time anyway, since there's a
: > default readonly accessor for each $.x variable.
: 
: OK; so add "method x {...};" to class Foo to keep it from blowing up.  Foo
: still has to track two scalars internally.  
: 
: Actually, it's worse than that: let's add "has Elephant $.x;" to Foo
: instead.  Since class trumps role, does $bar.m1 now work with an Elephant,
: or does it still work with a Cat?  

I think the attributes have to be considered to belong primarily to
the role, and a role that references one of its own attributes knows
that it is doing so to the exclusion of any other similarly named
attribute in the class or in a different role.  Accessing a role's
attribute from within a class or another role should really only work
as a fallback, if at all.  I think people should be encouraged to use
the methods where performance is not at a premium.  Most of these will
be private attributes in any event, so using the :method doesn't have
to do virtual dispatch.  But private attributes also belong primarily
to the role, and only secondarily to the class or other roles.  However,
the roles do implicitly trust each other by virtue of being composed
into the same class, so they can see each other's private methods.

Note that this means you can write roles that are only meaningful
when composed into a class with certain other roles or methods, and
cannot be used as mixins, since a mixin would never see the private
methods from an overridden base class.  The only way to do it as a
mixin is to have a composite role containing all the other roles, and
then mix that one role in all at once.  (Which is probably what you
want to do anyway for efficiency, when you know you have to mix
in multiple roles.)

Larry

Reply via email to