On Sun, Dec 14, 2003 at 03:16:16AM -0600, Jonathan Scott Duff wrote:
: So, if we follow the rules in the Traits paper, a role may have no
: semantic effect if the object's class already provides the necessary
: methods.  To *guarantee* that a role will modify an object's behavior,
: we need some sytactic clue.  Perhaps "shall"?
: 
:       my Person $pete shall Work;
: 
: Whatever methods Work defines will override corresponding methods of the
: same name (signature?) in the Person class. (With "will" or "does" just
: the opposite is true) And that same idea could extend to roles
: overriding roles easy enough:
: 
:       my Person $pete will Work shall Lead;
:       $pete.order();                          # calls Lead.order
: 
: i.e. if the class Person, and the roles Work and Lead all define a
: method called order(), then the Lead role's order() will be the one
: called.
: 
: I'm not sure that "will" works that way, but you get the idea.

I think there's a simple way to solve this: If you're changing the
policy of the class, then you're changing the class!  Derive from the
"defective" class and pull in the roles the way you prefer.  If we're
taking away the job of code reuse away from classes and giving it to
roles, then the only job left to classes is object policy.  Let's not
take that away too.

: WRT to the classes cooperation, should a class be able to say "You
: can't override this method"?
: 
:       method foo is forever { ... }
: 
: Seems like it would make it harder for the programmers to debug in the
: event of problems.  I guess that could be mitigated by clear error
: reporting and rampant object introspection.

I'm deeply suspicious of any trait resembling "final".  The way
to prevent people from overriding your interface is to write the
interface good enough that no one will want to override it.  Good
luck.  :-)

[begin digression]

The other reason for "final" is to make it easy for the compiler
to optimize.  That's also problematical.  As implemented by Java,
it's a premature optimization.  The point at which you'd like to
know this sort of thing is just after parsing the entire program and
just before code generation.  And the promises have to come from
the users of interfaces, not the providers, because the providers
don't know how their services are going to be used.  Methods, roles,
and classes may never declare themselves final.  They may be declared
final only by the agreement of all their users.

But the agreement could be implied by silence.  If, by the time the
entire program is parsed, nobody has said they want to extend an
interface, then the interface can be considered closed.  In other
words, if you think you *might* want to extend an interface at run
time, you'd better say so at compile time somehow.  I think that's
about as far as we can push it in the "final" direction.

[end digression]

: > I'm starting to think that any methods declared in roles are automatically
: > considered "multi" when composed, whether so declared or not.
: 
: Hmm. So that would mean that we'd need a syntax for method replacement
: when we wanted it (which we'd need anyway if the method was our smallest
: unit of reuse rather than the role) and the only time we would get an
: error is when 2 (or more) roles included in a composition have exactly
: the same signature.

Right, I think.

: [slight digression, but methods are really singleton roles aren't they?]

In a sense, yes.  Though just as with singleton classes, the type and
the thing it represents should not be confused.

: I'm not sure now whether I like idea of "shall" at all now. It seems
: better to just have every method of a role declare that it replaces the
: same-name method of the class. If the class doesn't want future roles
: replacing a given method, then we get an error. Oh, but without "shall",
: composition order would matter and there'd be no visual cue at
: composition time that a particular role is special. Drat.
: 
: Surely we would need a way to do same-signature replacement on methods
: too? This would mildly argue against an implicit "multi".

I still think the right way to change policy is to write your own class
that *doesn't* define the methods you want the roles to override.  The
name of a class has to represent *something*, if it doesn't represent
a fixed set of methods.  I submit that it represents a consistent policy.
A different policy should have a different class name.

So I think that classes have to be in charge of role composition.
The actor chooses how to play the part, not vice versa.  To the extent
that the actor can't choose, we're looking at the actor's traits,
not the actor's roles.

I try not to confuse roles and traits in my own life.  Being the Perl
god is a role.  Being a stubborn cuss is a trait.  :-)

Larry

Reply via email to