1

Here is a short example of casting a child class to a parent, and then calling a method.

I expected the foo method to get called in the child class, not the parent class. But, I am getting a compile error saying that the parent class doesn't have this method.

Why does Java care whether the parent class has it, if I'm only calling it on the child class?

public static void main(String[] args)
{
    A a = new A();
    B b = new B();

    b.foo(1, 2, 3); // Ok

    ((A) b).foo(1, 2); // Also ok. 
                       // Prints "In foo(int, int) method of class B"

    ((A) b).foo(1, 2, 3); // Will not compile

}

// later in the code...

class A 
{
    public int foo(int a, int b) 
    {
        System.out.println("In foo(int, int) method of class A");
        return 1;
    }
}

class B extends A 
{

    public int foo(int a, int b) 
    {
        System.out.println("In foo(int, int) method of class B");
        return 0;
    }
    public int foo(int a, int b, int c) 
    {
        System.out.println("In foo(int, int, int) method of class B");
        return -1;
    }
}
Katherine
  • 207
  • 1
  • 3
  • 11

4 Answers4

1

((A) b) is treated as A, although it's foo(int, int) is that of B's.

That means, because ((A) b) is known as A, you can only call methods that A has.

A only has foo(int, int), so you cannot call foo(int, int, int).

Hyun I Kim
  • 589
  • 1
  • 3
  • 14
0

The issue you're facing is related to the concept of method overloading.

foo(int a, int b, int c) is not a method in A. Although all the methods you've defined have the same name, they are treated as separate methods because they each have a different number of parameters.

When you attempt to call ((A) b).foo(1, 2, 3), b is treated as an instance of A. Java tries to find a method called foo in A with three parameters but cannot find it because it doesn't exist.

Anil
  • 655
  • 1
  • 11
  • 25
0
((A) b).foo(1, 2, 3);

The above code can be visualized as:

A a = (A)b;
a.foo(1, 2, 3);

As you can see the reference variable here is of type 'A' and all the method name resolutions should be based on the type 'A'. foo(...) with three parameters (the overloaded method) does not exist in A and so it throws an error.

ptk
  • 105
  • 9
  • Thank you. But.... if we think of it this way, why does my ((A) b).foo(1,2) call B’s method and not A’s? – Katherine Oct 16 '19 at 05:44
  • The method resolution happens based on the reference variable. This happens at the compile time. You can refer this link https://stackoverflow.com/questions/9223938/java-is-method-name-signature-resolution-done-statically-compile-time. But the actual method to call is decided at the run-time based on the actual object instantiated. For this reason, the method is invoked on the Object of B in your example. – ptk Oct 16 '19 at 06:50
0

((A) b).foo(1, 2); Works because A has the method foo with matching signature, but it executes B's foo instead since at runtime jvm can understand it's working with an instance of B. This is not available in the other method.

((A) b).foo(1, 2, 3); 
//is equivalent to
A b1 = new B();
b1.foo(1, 2, 3);

Java is statically typed, and as far as the compiler can see you are attempting to invoke a non existent method on type A and complaints. Compiler does not know what the runtime type is.

Martin'sRun
  • 522
  • 3
  • 11
  • Thank you. This makes sense. One follow up question: how is the JVM able to figure out at runtime that b is actually an instance of B, but the compiler is not? I should probably go look up a thread about that... – Katherine Oct 16 '19 at 05:47
  • Compiler works on what it can see, it cannot assume what the runtime type is. For example, you could pass in B objects as parameters to a method expecting A, or store B's in lists of A. – Martin'sRun Oct 17 '19 at 01:02
  • Not sure if it helps, but take a look at https://stackoverflow.com/questions/20783266/what-is-the-difference-between-dynamic-and-static-polymorphism-in-java – Martin'sRun Oct 17 '19 at 05:18