-1

I don't get how we managed to invoke constructor without parameters in class A at all. How upcasting works in this particular example? When we produce A ab = bb; what exactly ab refers to?

public class A {
    public Integer a;
    public Float b;

    public A() {
        a = 1;
        b = 1.0f;
    }

    public A(Integer x) {
        a = 2;
        b = 2.0f;
    }

    public int f(long x) {
        return 3;
    }

    public int f(double x) {
        return 4;
    }

}
public class B extends A {
    public int a;

    public B(float x) {
        a = 5;
    }

    public int f(int x) {
        return 6;
    }

    public int f(float x) {
        return 7;
    }

    public int f(double x) {
        return 8;
    }

}
public class M {
    public static void main(String[] args) {
        A aa = new A(1);
        System.out.println(aa.a + " " + aa.b);// OUT: [ 2 ] [2.0]

        int ret = aa.f(aa.b);
        System.out.println(ret); // OUT: [ 4 ]

        B bb = new B(6);
        A ab = bb;
        System.out.println(bb.a); // OUT: [ 5 ]
        System.out.println(ab.a + " " + ab.b);// OUT: [ 1 ] [1.0]

        ret = bb.f(1);
        System.out.println(ret); // OUT: [ 6 ]

        ret = ab.f(1.0f);
        System.out.println(ret); // OUT: [ 8 ]

        ret = ab.f(aa.a);
        System.out.println(ret); // OUT: [ 3 ]

        ret = bb.f(aa.b);
        System.out.println(ret); // OUT: [ 7 ]

    }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
cs_student
  • 23
  • 5
  • Side note: better to use primitive types rather than their reference wrapper counterparts unless you have a good reason for doing so. So use `int` rather than `Integer` and use `float` rather than `Float`, again, unless you have a decent reason for doing so (you don't here). – Hovercraft Full Of Eels Jan 04 '20 at 14:06
  • @Hovercraft Full Of Eels. How did we manage to get results 1 and 1.0 from constructor in class A? How ab.a is equal to 1? Those values are only available through constructor but did we call it? – cs_student Jan 04 '20 at 14:29
  • Fields are not overridden. And the default constructor *is* called. – Hovercraft Full Of Eels Jan 04 '20 at 14:32

1 Answers1

1

When we produce A ab = bb; what exactly ab refers to?

It references bb, but as an A, i.e. one can only call methods and attributes defined in A. There is no new object constructed. You can see this by checking System.out.println(bb == ab);, which will evaluate as true. This concept is known as attribute- or field-hiding.

This also is the reason why ab.a returns 1, because the attribute a (of type Integer) within A is accessed. If one would, on the other hand, access bb.a, one would get the attribute a (ob type int) within B, which is initialzed to be 5. Keep in mind that, if you construct a B, there is always an explicit or implicit call to a superclass constructor as defined in JLS, §12.5.

Turing85
  • 18,217
  • 7
  • 33
  • 58
  • can you please explain why result ab.a was equal 1? – cs_student Jan 04 '20 at 14:12
  • Because with `ab.a`, you access `A`'s attribute `a` (the `Integer`), which was initialzed with `1`. If you access `bb.a`, you access `B`'s attribute `a` (the `int`), which is initialized with `5`. This is known as [attribute hiding](https://docs.oracle.com/javase/tutorial/java/IandI/hidevariables.html) and is a mechanism within Java's inheritance model. – Turing85 Jan 04 '20 at 14:35