In a message dated Fri, 29 Sep 2006, Aaron Sherman writes:
First the high-level point: I'm dropping the RFC, because, as TimToady
pointed out on IRC, we're not quite far enough down the line to see the
breadth or certainty of the need yet.
Yes, but I don't think the conversation should stop. These are important
semantics of the object model and we should be at least roughly on the
same page so that when someone gets the tuits to work on it, it's clear
what the direction is.
That said, this is a different point, above and I think it's an easy one to
take on.
role A { method x() {...} }
class B { does A; }
does generate an error per "If a role merely declares methods without
defining them, it degenerates to an interface:" from S12.
However, that's not to say that a class can't be abstract, just that a class
that does an interface (a role with nothing but abstract methods) must
implement the role's interface.
So why would it generate an error? Why wouldn't it merely result in B
being abstract too, assuming that contra my prior mail, classes can be
abstract? Do you have to be explicit about it and say
role A { method x() { ... } }
class B { does A; method x() { ... } }
? That seems un-Perlishly verbose to me; we had DRY before Ruby ever did.
Nothing is said of what happens when you compose a role that has both
defined and undefined methods, but IMHO, that's at most a warning if
they remain undefined after composition, since you might want to use
that class as a trait at runtime where target objects will define that
method.
As I said on IRC, I don't read the part of S12 you quote as being the
definition of interface; I merely read it as being an analogy to the
concept of interface found in other languages. I'd find it absurd if
merely changing
role Existential { method is { ... }; method isnt { ... } }
to
role Existential { method is { ... }; method isn't { ! .is } }
resulted in the role changing its instantiability.
Certainly this:
class A { method x() {...} }
is very explicit, and should be allowed, given that it is a promise that
"sometime before x is called, it will be defined." It's a runtime error if
that promise is not kept.
Did you mean to have "class B" and "does A" there, as in my un-Perlish
example above? If so, then see my response above. If not... I'm a little
surprised. Since roles and classes share the package namespace, I
wouldn't expect you to be able to declare a class with the same name as a
preexisting role, even if you implemented all the role's interfaces within
that class....
One more point for the hypothetical future object-model
designer/implementer with the even more hypothetical tuits, so that it
doesn't get lost: note that in a DBC context, { ... } is insufficient for
an abstract routine. PRE and POST blocks would ordinarily be included as
well. A routine missing a PRE or POST would be considered to have:
method is {
PRE { True }
POST { True }
...
}
which under DBC rules would be the same as having no POST at all... but
would unfortunately cause any future PREs to be ignored!
(Under design-by-contract rules, POSTs are and-ed from least-derived to
most-derived, but PREs are or-ed. In fact, in Eiffel, PRE is called
"require" and POST is called "ensure", but only in base classes; in
derived classes, you must type "require else" and "ensure then" to make
explicit that your assertions are being or-ed or and-ed with assertions
elsewhere in code.)
Trey