Brad Bowman wrote:
Hi,

Did you mean to go off list?

No, I didn't.

Jonathan Lang wrote:
> Brad Bowman wrote:
>> Does the "class GenSquare does GenEqual does GenPointMixin" line imply
>> an ordering of class composition?
>
> No.  This was a conscious design decision: the order in which you
> compose roles has no effect on the result.

Great.  That's what I want.

>> I would like a way to make one Role to require that the target class
>> "does" another abstract Role, is there already such a technique?
>
> What's wrong with just having the role compose the other abstract role
> itself?  That is, instead of "role Bar requires Baz; class Foo does
> Bar does Baz", why not say "role Bar does Baz; class Foo does Bar"?
>

That would work, as long as you get a compile time error when
Foo doesn't implement the Baz abstract interface.

...which is exactly what happens.  Mind you, the compile-time error
won't report that Baz::method is unimplemented, or even that
Bar::method is unimplemented; it will report that Foo::method is
unimplemented.  It's up to the programmer to figure out where
Foo::method came from, on the off chance that it matters.

It's perhaps also less clear that the indirect Baz mixin must be
implemented.

If Bar does Baz, you can read that as "Bar requires Baz to be
implemented, too."

There's a tendency, when dealing with traditional inheritance systems,
to think of the primary function of a superclass as being a supplier
of implementations for any classes that inherit from it.  I submit
that this is the wrong way to think of roles: rather, a role is first
and foremost a source of interface requirements for whatever does that
role.  If a role includes a method declaration, that should be read as
"anything that does this role must provide a method that matches this
one's name and signature."  If a role does another role, that should
be read as "anything that does this role should conform to the
requirements of this other role as well."  Any implementations that a
role provides should be viewed as _sample_ implementations, to be used
if and only if you can find no reason not to use them.

BTW, this includes attributes: if a role declares a public attribute,
this should be read as that role requiring an accessor method for that
attribute; if whatever does the role redefines the methods (including
the accessor method) such that none of them refer to the attribute,
the attribute should not be mixed in.  If a role defines a private
attribute and then fails to define any methods that access that
attribute, the only way that that attribute should end up getting
mixed into something else is if whatever does the role that the
attribute is in provides the methods in question.  In summary,
attributes and method bodies in roles should be taken as _suggestions_
- only the public method names and signatures should be viewed as
requirements.

I guess any role could just declare some yada methods and leave it
at that.

That too.

Bear in mind that when you compose a role into another role, you are
under no obligation to replace yada methods with defined ones.  In
fact, it's even conceivable for you to replace a defined method with a
yada method if the default implementation from the other role isn't
suited to the current one.  The only time that you're required to
replace yada methods with defined methods is when you compose into a
class.

--
Jonathan "Dataweaver" Lang

Reply via email to