Overloading/Inheritance issue

Steve Schveighoffer schveiguy at yahoo.com
Fri Aug 3 06:45:19 PDT 2007


Regan Heath Wrote:

> Steve Schveighoffer wrote:
>  > My argument is not against this, as you will note that in these
>  > examples, both base and derived classes can match the call by some
>  > sort of implicit conversion.  In the case where both the base class
>  > and the derived class  match the call, I could care less if the
>  > derived class was called instead of the base class.
> 
> But, that's exactly the problem.
> 
> In fact example 2 shows that we currently have the undesirable and buggy 
> behaviour in the current D implementation, eg.
> 

Oh, I understand what you are saying.  However, undesirable behavior is unavoidable no matter which way we go.  It all depends on what you expect and what the user of the class expects.  My thought is that you have to pick one way, and just tell people that's the way it is and they have to live with it.  I'm speaking only of the case where both base and derived class can match the call exactly or through some implicit conversion.

On second thought, you could pick a third option for behavior, and say that if the derived class has no explicit match, but has implicit matches, and the base class has explicit or implicit matches, the compiler should error out saying it doesn't know which one you intended.  That would mean even less obscure bugs, forcing the user of the class to pick the one they want by explicitly casting the arguments or the object.

> I see the distinction, and it is the case with your original example as 
> you wanted it to call select() from the base class.
> 
> Interestingly, if the derived class "EpollSelector" had to conform to 
> the interface "ISelector" that the base class "AbstractSelector" 
> implements then the author of "EpollSelector" would have noticed and 
> added the 'alias' and this would never have come up.

One of the problems is that you would most likely re-use the unit test code for AbstractSelector, which means you would cast the EPollSelector instance to the AbstractSelector test code, hiding the actual problem.  The only way to find this is for the author to write test code that specifically uses the derived class to call the base class' functions that he expects to still exist.  I think this is an unnecessary requirement for finding this problem, especially when there is no reason to want it the other way.

> 
> This change you suggest does violate D's current 'simple' lookup rules 
> and go against the original reasoning of:
> 
> "His argument is that one can easilly miss an overload of f() somewhere 
> in a complex class heirarchy, and argues that one should not need to 
> understand everything about a class heirarchy in order to derive from it."

So by this argument, Walter is saying that the desired behavior of the author is to only make available the overloaded methods that the derived class overrides?  I totally disagree.  Why would an author want to do this?  If it is to hide the other overloads, he has failed, because the user of the class can just cast to a base class in order to call the method they want.  If the author desires to hide this from the user of the class, then his class can be used in ways he didn't intend.  An author who overrides a class ignorant of all the functionality the class provides is IMHO a poor coder.  Even with your example, with the "squareIt" bug, I would never accept code like that as correct.  The argument above seems to be defending that type of behavior as desired.  In my opinion, a class should behave the same no matter how you look at it, i.e. how you cast it.

> 
> So, if you want to see this change you're going to have to post 
> something convincing addressing this, probably with some real-life examples.

I've posted one.  Evidently others have had similar problems.  I'm not sure I need any more examples, I think the fundamental argument against is flawed, at least in this specific case where the base class can be used but the derived class cannot.  I'm also leaning towards my further argument that the compiler should error out if the desired behavior of the coder is not obvious.

> 
>  > I'd bet we'd see 0 obscure bugs if this change was made ;)   As I've
>  > mentioned, I've already seen one obscure bug caused by the current
>  > implementation...
> 
> Not to nit pick but is the bug you're referring to the problem you had 
> with Tango's tango.io.selector.EPollSelector?  If so I wouldn't say that 
> bug was 'oscure' because presumably it gave you an error on compile, as 
> opposed to silently failing on some customers system which is what 
> happens in the two examples given by Walter (including example 2 above 
> which fails in D today).

It took me several hours of poking to figure out why the selector thing didn't compile, then several hours of writing test code to demonstrate the issue, researching whether this was desired behavior, and even then, I couldn't find any definite answer in the D spec, which led me to post this thread.  I'd say that's a pretty obscure problem :)  Not to mention that it's not MY bug.  The author probably still doesn't know there is a problem, so from his point of view, the bug is still at large without him noticing.

-Steve



More information about the Digitalmars-d mailing list