1

I've been trying to teach myself inheritance using java, but I am really confused and it seems online youtube videos/looking at previous questions are not helping at all. I tried the practice problems on this website: http://javaconceptoftheday.com/java-inheritance-practice-coding-questions/ , but I am having trouble with questions 2, 3, and 7.

In question 2, since the constructor of object a is B(), why wouldn't it print class B's i value instead of class a's? Instead it prints class a's and I have no idea why.

In question 3, is the reason that the program prints 1 2 3 because there are no constructors and it's just the function? I know when you inherit from a class, you basically act as if all of its functions are in the subclass, so do you basically just pretend class C says:

System.out.println(1);

System.out.println(2);

System.out.println(3);?

In question 7, since the constructor is a C() constructor, why does it still go through the code in the constructor for class A and class B?

Thank you for any help you can give, inheritance is just one of the topics I did not cover in my intro to programming class so I'm trying to fill in all of the blanks before fall semester starts.

Code for question 2:

class A
{
    int i = 10;
}

class B extends A
{
    int i = 20;
}

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

        System.out.println(a.i);
    }
}

Code for question 3:

class A
{
    {
        System.out.println(1);
    }
}

class B extends A
{
    {
        System.out.println(2);
    }
}

class C extends B
{
    {
        System.out.println(3);
    }
}

public class MainClass
{
    public static void main(String[] args)
    {
        C c = new C();
    }
}

Code for question 7:

class A
{
    public A()
    {
        System.out.println("Class A Constructor");
    }
}

class B extends A
{
    public B()
    {
        System.out.println("Class B Constructor");
    }
}

class C extends B
{
    public C()
    {
        System.out.println("Class C Constructor");
    }
}

public class MainClass
{
    public static void main(String[] args)
    {
        C c = new C();
    }
}
vp123
  • 61
  • 5
  • 2
    Could you please include the questions from the website in your question? (People are less likely to click a link, and if the link ever goes bad this question won't be answerable.) – GBlodgett Jun 03 '18 at 18:41
  • 2) basically because you cannot overwrite fields. 3) those are static initializer blocks, I do not know the exact conditions for their execution but the order seems correct, 7) because you still have to set up the fields in `B` and `A`, and they are called via an implicit `super()` which is "inserted" in all three no-arg constructors. – luk2302 Jun 03 '18 at 18:43
  • @GBlodgett thank you for the advice! I updated the question. – vp123 Jun 03 '18 at 18:46
  • @luk2302 so anytime a class inherits from another class, in its constructor there's a "super()" function that you don't see? (Basically anytime you call the constructor of the subclass, the superclass constructor is called? – vp123 Jun 03 '18 at 18:48
  • If you do not write `super(...)` or `this(...)` on your own there, then yes there will an "invisible" `super();`, you always have to end up calling a constructor of the parent class. – luk2302 Jun 03 '18 at 18:49
  • @luk2302 gotcha that makes more sense. And then for question 2, why isn't it printing 20 since the constructor is a B()? Or is the first class the one you base it off of when you create a new object using class object_name = new class() ? – vp123 Jun 03 '18 at 18:52
  • that has nothing to with constructors. You tell the compiler you have an instance of `A` and access its `i`, since fields cannot be overriden you end up getting 20, if you would simply change the type of the variable to `B` and leave the rest as is you would get `10`. – luk2302 Jun 03 '18 at 18:53
  • @luk2302 So anytime you're working with an object using inheritance, you only use the instance of the object, not the constructor? For example if for the code there was a subclass of B called C and I did A object = new C(), and then did System.out.println(object.i), it would still print 10? – vp123 Jun 03 '18 at 18:57

2 Answers2

1

Q2) The polymorphic behavior of the Java language works with methods and not member variables: they designed the language to bind member variables at compile time, methods at run-time.

Q3) It's called as instance initialization block. Every instance of a subclass implicitly contains an instance of its superclass. So call order is commenced from class A, B then C.

Q7) Same reason of Q3 applies for the question

  • This is starting to clear a lot of it up for me, thank you! So say I create an object by doing: A object = new C();, basically object's functions are treated as the functions of C because it is overridden by class C, but its variables are defined by A? – vp123 Jun 03 '18 at 19:00
  • Thank you! I think I got it now. And then conversely, if I create an instance of an object by doing C object = new C();, it's variables AND functions are defined by C, but it still has an invisible super() in its constructor so if class A and class B constructors have System.out.println() in them, it'll print them as well right? – vp123 Jun 03 '18 at 19:02
  • @vp123, Yes, there are `super()` calls implicitly. – Soner from The Ottoman Empire Jun 03 '18 at 19:05
0

First off, I think you should take a look at Oracle's Java tutorial, mainly the one on Classes and the one on Inheritance.


Let's start with Question 2:

class A {
    int i = 10;
}

class B extends A {
    int i = 20;
}

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

        System.out.println(a.i);
    }
}

Since A and B have a member of same name, B hides the member in A. In essence, an instance of B has two members i: one from A, and one from B. Within method main, you write A a = new B();, i.e. the static type of a is A, the runtime type of a is B. When you now access members, the static type decides, which member (A's or B's) is selected. Thus, the i in A is selected. Why is that? If we modify the example a little bit, we see why:

class A {
    int i = 100;
}

class B extends A {
    String i = "Hello";
}

class Ideone {
    public static void main (String[] args) throws java.lang.Exception {
        A a = new B();
        int i = a.i;
        System.out.println(i);

        String s = ((B) a).i;
        System.out.println(s);
    }
}

(Run it on ideone.com)

In this example, B again hides the member i in A. But this time, the fields have a different type. Nevertheless, whenever you access the member i in A, you expect an int, not a String. This is the reason why the static type decides, which member is selected.


Question 3:

class A {
    {
        System.out.println(1);
    }
}

class B extends A {
    {
        System.out.println(2);
    }
}

class C extends B {
    {
        System.out.println(3);
    }
}

public class MainClass {
    public static void main(String[] args) {
        C c = new C();
    }
}

For this, we need to know three things:

  • If there is no constructor provided for a class, it has an implicit default constructor.
  • If the first statement in a constructor is neither this(...) nor super(...), then it is an implicit super();.
  • initializers of a class are executed after the superclass-constructor, but before the own constructor.

What can we conclude from those three statements? If we initialize any object, the first thing we have to execute the superclass-constructor. This leads to a constructor-cascade from the type you try to initialize up to Object. Thus, we see the output in-order:

1
2
3

Question 7:

class A {
    public A() {
        System.out.println("Class A Constructor");
    }
}

class B extends A {
    public B() {
        System.out.println("Class B Constructor");
    }
}

class C extends B {
    public C() {
        System.out.println("Class C Constructor");
    }
}

public class MainClass {
    public static void main(String[] args) {
        C c = new C();
    }
}

The answer to this question is already answered through my answer to the last question: If the first statement of a constructor is neither this(...) nor super(...), it is implicitly super(). Thus, from C's constructor we call B's constructor, and from B's constructor, we call A's constructor. So we, again, get the output in Order:

Class A Constructor
Class B Constructor
Class C Constructor
Turing85
  • 18,217
  • 7
  • 33
  • 58