Daniel,
I think I understand the issue better now.
Not that your idea - how base class provides implementation for reuse
by subclasses and using packages to specify this protocol - was impossible
to understand from your first mail.
I see that my doubts and the form of my previous email are caused by the fact that I still
don't completely understand OOP and classes, despite I use it for years and spent
some efforts on understanding it.
I understand how the program will be behave when I use this or that language feature;
I have partially understanding and partially "feeling" about what is right, know common
patterns how OOP is applied in different situations. But still I don't have a mental model
which clearly defines all the concepts and fits them together: classes, protocols,
modularity... how these concepts overlap? what does it mean to "implement a class"?..
what belongs to a class and what does not, and so on.
BTW, I've been constantly thinking for maybe 3 days and made several steps further
in clarifying my mental model (although open questions remain).
I am taking back my words that public and protected are single protocol -
I understand the nature of this separation better now.
Minor clarification of the previous mail:
> Taking you literally, we do not need a new CL feature.
> But translating what you're saying into the terms
> I am using, you're saying that we need only one
> protocol, whereas I am saying that it's better
> to have two.
Actually I meant that even for Java it could be better to have only package
public and package private, as Common Lisp has; without public/private/protected
for classes. In your example with the Point class, getX, getY would be
package public, and the data members x and y would be package private
(and at any time may be changed to an angle and a distance from the origin,
without breaking the clients). Maybe in Java it will cause some inconvenience:
e.g. with single inheritance in some situations reusing implementation
may require lot of typing if we want to delegate method implementations to an
"implementation utility" class from other package: void m() {implForReuse.m();}.
But Java is not the subject here, so we may leave it aside.
The "print" and "to_string" example is illustrative; although the people who relied
on the fact that the "print" uses "to_string" were relying on an undocumented feature;
it's their own bug, not the library vendor's. Therefore IMHO the Ada 95 solution is not
obligatory, I agree that people should expect only documented behaviour to be preserved
in future versions. But of course, reducing the number of such undocumented entry points into
the implementation may help them to avoid such bugs.
The ParaSail link is really interesting. BTW, I suppose the idea to plug-in programmer defined
static checks into compiler is not intrinsically contradicting with the Common Lisp - maybe
it's possible to implement something in this fashion for Lisp too (with certain limitations, but
useful in practice). I've been thinking a little about that before (if we can introduce new language
constructs expanded at compile time, why can't we implement compile time checks); and it's
interesting to see somebody actually implements it for a language.
To not loose the point of this thread, as I said the idea to use packages to specify protocol
for subclasses seems right. It's necessary to try it in practice.
Best regards,
- Anton