which foo(x)

From: Rick Trotter (rht325_at_yahoo.com)
Date: 10/29/03


Date: 29 Oct 2003 06:39:04 -0800

I was trying to write some polymorphic application code and found that
a superclass method implementation gets invoked when I expect a
subclass implementation. Here's how I have abstracted the problem.

I have a base class - ClassA. I have a subclass of ClassA - ClassB.
Both classes implement foo() - exact same method signature.

My application code instantiates instances of ClassB (and siblings)
via a marshaler, and only knows that the object it references is a
"kind of" ClassA. I simulate this as shown below.

ClassA a = (ClassA) Class.forName("ClassB").newInstance();

Now, if I send a.foo(), I see that the implementation overriden in
ClassB is invoked - as I had hoped and expected.

But really what I am aiming for is something with a different twist.

I have another class hierarchy with a base class - ClassX - and a
subclass - ClassY.

I have implemented ClassA.foo(ClassX) and ClassB.foo(ClassY).

Instances of ClassX and ClassY are created outside the context of the
code that invokes foo(...). All this code knows is that it's got a
reference to an object which is a "kind of" ClassX. I simulate this as
shown below.

ClassX x = (ClassX) Class.forName("ClassY").newInstance();

If, in this scenario, I send a.foo(x) I see that it is the super
implementation of foo(...) that is invoked rather than the subclass
implementation of foo(...).

This was a big surprise to me. And it may seem as puzzling to some
that I found it surprising. After all, you note, the Java compiler
chose exactly the right implementation based on the information that I
provided.

I can kind of accept this, although I would argue that this behavior
makes polymorphic code really fragile and difficult to debug, since
runtime behavior is different from the language semantics due to ...
?compiler optimization?. (Coming to Java from a Smalltalk background,
as I do, the complexity here seems a bit bizarre)

But wait. By this reasoning, shouldn't I have gotten the superclass
implementation of foo(void) in the first scenario?

Just by way of exploring this puzzle a little further, I added another
scenario. Suppose I have a variable declared as "ClassB b", and send
"foo(x)" (where, as above 'x' is an instance of ClassY). This is at
least consistent with scenario #2 - I get the super implementation
because the compiler doesn't know that 'x' is actually a reference to
an instance of ClassY.

So far, then, it seems like scenario #1 is a bug, since - although
it's what I wanted - it's inconsistent with the other two scenarios.
Is there another explanation?

-rht

public class Testcase5 {

        public static void main(String argv[]) {
                ClassA a;
                ClassB b;
                ClassX x;
                try {
                        a = (ClassA) Class.forName("ClassB").newInstance();
                        b = (ClassB) Class.forName("ClassB").newInstance();
                        x = (ClassX) Class.forName("ClassY").newInstance();
                } catch (Exception e) {
                        System.err.println(e.getMessage());
                        return;
                }
                
                b.foo(); // out: "B.foo()"
                a.foo(); // out: "B.foo()"

                b.foo(x); // out: "A.foo(x)"
                a.foo(x); // out: "A.foo(x)"
        }
}



Relevant Pages

  • which foo(x)
    ... I have a subclass of ClassA - ClassB. ... Instances of ClassX and ClassY are created outside the context of the ... code that invokes foo. ... If, in this scenario, I send a.fooI see that it is the super ...
    (comp.lang.java)
  • Re: why is a superclass allowed to access protected methods of a subclass?
    ... > Are you saying that when Parent invokes SecondGeneration child.superClass ... > subclass method is definately being invoked from the superclass. ... > Parent.testParent and it prints "I'm in protected superClass of child. ... scenario Eclipse got confused and was saying that it was the parent's method ...
    (comp.lang.java.programmer)
  • RE: Null Reference Exception after Forms.TabPageCollection.Remove(
    ... The KB 893005 was addressing a case whose scenario was different from ... exception if an error occurs while unsubclassing the control. ... wouldn't detect this situation correctly and could free the subclass ... They were all solved by the hotfix 893005. ...
    (microsoft.public.dotnet.framework.windowsforms)
  • Notification when a window is subclassed
    ... The scenario am dealing with is that I subclass a window to take a ... is seeming to subclass the Window once again. ...
    (microsoft.public.vc.mfc)