Object initialisation - The relation of the constructor to class type and method access

Phoenix :

I have the following code:

package testapp;

class Calculation {

    public Calculation(){}

    public void addition(int x, int y) {   }

    public void Subtraction(int x, int y) {   }
}

class My_Calculation extends Calculation {

    public My_Calculation(){}

    public void multiplication(int x, int y) {   }
}

public class TestApp {

    public static void main(String[] args) {

        int a = 20, b = 10;

        My_Calculation demo = new My_Calculation();
        demo.addition(a, b);
        demo.Subtraction(a, b);
        demo.multiplication(a, b);
        System.out.println(demo.getClass().getName());

        Calculation d = new Calculation();
        d.Subtraction(b, b);
        d.addition(b, b);
        // no multiplication
        System.out.println(d.getClass().getName());

        Calculation d2 = new My_Calculation();
        d2.Subtraction(b, b);
        d2.addition(b, b);
        // no multiplication
        System.out.println(d2.getClass().getName());
    } 
}

The output is this:

demo = testapp.My_Calculation

d = testapp.Calculation

d2 = testapp.My_Calculation

The following statement is a declaration that references variable name d2 to object type Calculation:

Calculation d2;

The following statement is an initialisation that calls My_Calculation constructor.

Calculation d2 = new My_Calculation();

When I run the following code, the output states that d2 is of class type My_Calculation but gives access to the methods within Calculation class.

System.out.println(d2.getClass().getName());

Output: testapp.My_Calculation

Access: addition; subtraction

Now, my understanding tells me that if My_Calculation constructor is called I should either have:

1. access to multiplication ONLY, or

2. access to addition, subtraction and multiplication.

But, I actually get the inverse: access to addition and subtraction ONLY. Thus, I see this as counter-intuitive.

Could someone explain to me what is happening here to give me a coherent understanding of why an object of type: My_Calculation would have no access to its own methods but access to only the superclasses methods.

GhostCat salutes Monica C. :

Here:

Calculation d2 = new My_Calculation();

You create an object of type My_Calculation, but you assign it to a variable declared with the supertype! And the compiler isn't smart enough to "see" that d2 is actually of the child type. Thus the compiler prevents you from calling a method defined on that child type. Because to the compiler, d2 is known to be a Calculation!

Note that you can cast to tell the compiler "I know better":

( (My_Calculation) d2) ).multiplication(...

that would work at compile time, and also at runtime!

Your misconception starts here:

Calculation d2 = new My_Calculation();

What you do on the right hand side of the assignment is basically "forgotten" in the next line. Then the compiler only knows that you have some d2 of type Calculation!

Finally: yes, in your specific example, the compiler could easily determine the real type of d2. But there are many situations where that isn't easy, or even impossible. Thus the people behind Java decided to ignore such potential "knowledge".

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=115300&siteId=1