How should overruling of overloaded functions work?
Søren J. Løvborg
web at kwi.dk
Sun Aug 20 16:35:17 PDT 2006
> What jumps out when you just look at the function stubs for base and
> derived is that Monitorable_stack chose not to override push_many. It
> certainly is one of the functions you ought to be interested in
> intercepting.
>
> The only plausible conclusion is that an inference has been made about
> Stack's hidden implementation. It turns out that was exactly the reasoning
> behind the article's author. Yet again has to violate "a central OO
> principle like implementation hiding" in order to make his point.
Imagine that push_many was added to the base class in a later version, after
Stack was created. Then you have the exact same problem, without making any
assumptions about the implementation as such. And the same problem is used
to justify the hiding of overloaded methods in C++ (and hence, D), as
discussed in the original post.
The difference between extending a base class and implementing an interface
is that if you add a new method to the class, it can introduce subtle bugs,
while if you add it to an interface, it's a compile-time error unless you
also add it to every implementation of that interface.
The reason for extending a class is to override "hook" methods to change the
functionality of the class, e.g. the paint() method of a GUI control, or the
add() method of a list. However, when you do this, you no longer only have
to worry about the "public interface" for the class (all the public methods,
which users of the class may call), but also about keeping a consistent
"protected interface".
In the public interface, the implementor simply marks the public methods
with visibility "public", and he's done.
/* Call this to add an object onto the stack. */
public void push(Object o)
The contract for using the public interface is simple: Provide valid
argument values, and the method will do what it's supposed to.
With the "protected interface", correct visibility is the least of the
problems. The implementor needs to define exactly which methods may be
overriden by subclasses (not neccessarily all of the public methods), and
the exact semantics of each method, for instance:
/* This is guaranteed to be called exactly once for every object added.
*/
public void push(Object o)
The contract for using the "protected interface" isn't simple. When
subclassing, you need to read the documentation, or you'll introduce hard to
find bugs. The contract cannot be enforced by the compiler, nor can it be
enforced at runtime.
So yes, you can produce code that works perfectly, in which you extend
classes (obviously -- everybody does it).
You can also produce code that works perfectly, in which the member
variables of all classes are public.
By eliminating or minimizing both, you might save yourself some trouble. Or
you might not.
I, personally, am not letting go of subclasses just yet...
Søren J. Løvborg
web at kwi.dk
More information about the Digitalmars-d
mailing list