-2

I'm a student, learning Java. I know, protected means access from children or the same package. Here we inherit and override a protected method. And after such an action, whenever the base class wants to call its own method it calls the new overridden one from the subclass. I've been debugging this for a while and marked the execution order with comments. But I can't understand why doesn't it call the base method when I clearly call that from inside the base class constructor?

public class Solution {

    public static void main(String[] args) {
        new B(); // first
    }

    public static class A {

        public A() {
            initialize(); // third
        }

        protected void initialize() {
            System.out.println("class A"); // we never go here
        }
    }

    public static class B extends A {

        public B() {
            super(); // second
            initialize(); // fifth
        }

        protected void initialize() {
            System.out.println("class B"); // fourth, sixth
        }
    }
}

That's a task from one website, so basically the solution is to change access modifier of the initialize method from protected to private. But I still fail to understand why is the problem happening.

Sam
  • 1,832
  • 19
  • 35

2 Answers2

1

What you're trying to do is defeat the purpose of polymorphism. You can, but you have to make the call specifically. Add a Boolean to your method and call the super.initialize(Boolean). Again, this defeats polymorphism and the extending class HAS to know about the super class. NOT VERY ELEGANT.

public class Solution {
    public static void main(String[] args) {
        new B(); // first
    }

    public static class A {

    public static boolean USE_SUPER = true;

        public A() {
            initialize(USE_SUPER); 
        }

        protected void initialize(boolean unusedHere) {
            System.out.println("class A");
        }
    }

     public static class B extends A {
         public static boolean USE_EXTENDED = false;

         public B() {
            super();
            initialize(USE_EXTENDED);
         }

    protected void initialize(boolean useSuper) {
        if (useSuper)
                super.initialize(useSuper);
        else
                 System.out.println("class B");
     }
}

  }
Dakoda
  • 175
  • 7
  • @SamKruglov, If A.initialize() differs from B.initialize(), why use polymorphism? Call them differently. A.initializeA() and B.initializeB(). – Dakoda May 30 '17 at 15:41
  • Oh yeah, I think I got it. We created only object B, therefore we only have methods from that perspective. And calling method from the parent only implies polymorphism. Thanks! – Sam May 30 '17 at 16:10
0

As Dakoda answered, the root cause is polymorphism. That means we may create child objects, but refer to them as their parent type and when we call the methods of the parent layer we actually refer to the child's methods.

In my case, I create a child object (marked //first) B, which has its own body of the initialize method. One nuance of the inheritance is that it doesn't include constructors, so I can call the parent's constructor (marked //second). Inside the parent's constructor, I call the initialize method - that is the polymorphism because I call the method of the child from its parent abstraction layer.

Here is the answer to the question - this happens, because we only allocated memory for a B instance, that means, we took A as our base and started to extend it (while we can overwrite anything inside). The only two things we did are:

  1. We created a constructor (it wasn't included in the base, as mentioned above)
  2. We overwrote the initialize method code. The code for this method that is inside the base is now lost for this object.

This concept of polymorphism is designed that way and there is no way for us to access the base method unless we specifically create an object that is either A itself or a child that doesn't overwrite this method.

Sam
  • 1,832
  • 19
  • 35