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