From: Fernando Mato Mira
Subject: Encapsulating CLOS (was: Diff. CLOS vs C++)
Date:
Message-ID: <2fc4f0$8p3@disuns2.epfl.ch>
In article <··········@disuns2.epfl.ch>, I wrote:
[a lot of package hacks deleted]
(In the following, I assume a package per class, and might
use a class name as the name of its associated package).
There is one big problem with the scheme I described:
Given a class X with subclasses Y, where a symbol
S is exported from X and unexported from Y,
if you (USE-CLASS 'Y), now you have to write
(slot-value x 'X:S)
Now, referring to X:S seems completely OK, after all
it is an exported symbol. However, if x is happens
to be of type Y, you're being allowed to do exactly
what we try to prevent.
The problem is even worse if you have another subclass
of X (say, Z) where S is not unexported, as evaluating
(USE-CLASS 'Z) would now intern X:S again, and you
could write (slot-value x 'S), which is right for
X and Z, but totally wrong for Y.
Now, I have been thinking about the slot renaming issue
ever since I moved back from Eiffel, and I think I came
out with a good strategy for this. However, a couple
of weeks ago I realized that this was working to good, and
that now I couldn't see why I was using accessors instead
of slot-value for normal slots. I had never thought
about the `unexport' issue (there was no unexport in
Eiffel 2, after all).
In Eiffel, a function can refer to the internal features
of `Current' (self), without concern for exporting issues
(but if you access the feature via `.', you're considered
a client, and should have the proper rights).
In C++, a member or friend function can also `look inside'.
So, given a class C, we can define functions in the
associated package C as C's friends. (Of course, a
package D of a subclass D of C, has to be considered
a 'subpackage' of C, and the appropriate package
engineering performed).
A function which is not a friend of a class is not
allowed to perform slot-value on the class (any
evaluation of slot-value on the class in a non-friend
package is wrong).
A friend defined for C accessing slot S, should
have no problem accessing S in D, even if D is deleted
(thanks to the MOP) or renamed. A method for
SLOT-VALUE-USING-CLASS with specializers D and C::S
takes care of the mapping.
For every slot that you want exported, you need an
accessor. Exporting the symbol is orthogonal to the
exporting concept here. A feature being private in D
means that
a) an accessor function is not defined
or
b) the accessor function is specialized
to raise an error when applied to an instance of
D (of course, this can be `re-exported' for
instances of a subclass of D).
As this is an important issue, I have crossposted this
quite heavily in order to get good ideas from smart people
in other net.hoods .
--
Fernando D. Mato Mira
Computer Graphics Lab
Swiss Federal Institute of Technology (EPFL) Phone : +41 (21) 693 - 5248
CH-1015 Lausanne FAX : +41 (21) 693 - 5328
Switzerland E-mail : ········@epfl.ch