[Prev][Next][Index][Thread]
abstraction with subtyping & Overloading considered harmful
> From rwh@cs.cmu.edu Tue Jun 23 13:06:17 1998
> From: Robert Harper <rwh@cs.cmu.edu>
>
> Can this be summarized by saying that a language ought to provide type
> abstraction mechanisms that allow you to reveal only that a type t is a
> subtype of another type T in a given context? The presence of such a
> construct is completely compatible with structural subtyping; it's just that
> in some contexts we hold a type t (partially) abstract by revealing only
> that t <: T. In other words: one shouldn't decide as a language design
> issue that types compare structurally or not, but rather whether the
> language should support constructs to restrict knowledge about subtyping
> relationships in certain contexts.
>
> Bob Harper
>
Bob's comments certainly summarize my feelings about structural versus by
declaration subtyping (or better yet matching): Use structural subtyping
and then provide a mechanism (as we have in the LOOM module system -
and Modula 3 did before us) to make declarations partially abstract so
that no other type could be a subtype (or match) the new one unless
they obtain access to hidden information.
We did feel it useful to have features to allow others to retrospectively
gain access to the hidden information in order to allow them to
subtype(match) the previously partially revealed type.
--------------(subject change)------------
I also wanted to comment briefly on the flurry of messages (starting with
Wadler's?) pointing out the important role that static method override
had on the apparent problems.
For a long time I've been meaning to sit down a write a brief article
for SIGPLAN Notices that fits within the "X considered harmful" series,
where X is "Combining dynamic method dispatch and static overriding".
Here are some of my favorite Java examples of simple yet obscure code
using everyone's favorite classes:
// All access restrictions (public/protected/private) omitted for clarity
class Point{
void equal(Point x){...} //*1*
}
class ColorPoint extends Point{
void equal(ColorPoint x){...} //*2*
}
Point p1 = new Point();
Point p2 = new ColorPoint();
ColorPoint cp = new ColorPoint();
For each method call, say which version of equal is called:
1. p1.equal(p1);
2. p1.equal(p2);
3. p2.equal(p1);
4. p2.equal(p2)
5. cp.equal(p1);
6. cp.equal(p2);
7. p1.equal(cp);
8. p2.equal(cp);
9. cp.equal(cp);
While the correct answers are not that hard and are easy to explain
retrospectively, I've seen very good programmers get confused on the answers.
Answers will be posted later in the week.
Hint:
Java's rules for overloading methods are different from C++'s.
In particular, C++ does not allow overloading across subclasses.
Thus in C++, ColorPoint's only know about the equal method with a
ColorPoint parameter. Thus two of the calls would be illegal in C++,
but they are legal in Java.
Kim Bruce