0

I'm having difficulty wrapping my head around this odd behavior of Java inheritance.

Say, I have Parent class with private method method1. Then there's a class Child that extends Parent class. Child also defines method called method1, but it is public. Please see below for example:

public class Main {
    public static void main(String[] args) {

        Parent p = new Child();
        p.method2();
    }
}

class Parent{
    private void method1() {
        System.out.println ( "Parent's method1()" ); 
    }

    public void method2() {
        System.out.println ( "Parent's method2()" ); 
        method1();
    }
}

class Child extends Parent { 
    public void method1() {
        System.out.println ( "Child's method1()" );
    }
}

What I don't understand is that the output is below!!!

Parent's method2()
Parent's method1()

I know that since method1 is private in Parent, method1 in Child has nothing to do with that of Parent. If so, then when method2 invokes method1, why is Parent's method1 is called not Child's? Especially when the actual type is Child.

It seems like there's absolutely no clue which method1 is called from method2. Am I missing a inheritance rule? Please please help!!!

GrinNare
  • 125
  • 1
  • 9
  • I'm having trouble finding a good link, but you might check out something like [this](http://skeletoncoder.blogspot.com/2006/09/java-tutorials-overloading-is-compile.html). The basic rule is that Java chooses overloads at compile-time (static binding) and overrides at run-time (dynamic binding). The actual JLS for why your example is the way it is is [right here](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.1) at the top (under "if the form is *MethodName*"), but I'm not sure that the JLS there is all that helpful without the background. – Radiodef Apr 19 '17 at 04:02
  • What does this have to do with 'order'? – user207421 Apr 19 '17 at 04:13

2 Answers2

2

private void method1() prevents the method from getting overridden.
Therefore, any child class cannot inherit this method1().
In your code, the child class has its own separate method1().


Parent p = new Child(); // We have p of Parent reference and is a Child object
p.method2(); // At compile time this statement binds the method2() from Parent class

Since only parent class has the method2(), it is been called.


However, suppose you had overridden this method in your Child class.

class Child extends Parent {
    public void method1() {
        System.out.println("Child's method1()");
    }
    public void method2() {
        System.out.println("Child's method2()");
    }
}

In this case, even at compile time, method2() is binded to Parent class.
But at runtime, the method2() from Child class is called. This is run-time polymorphism.

Thus output for the call p.method2() would have been

Child's method2()
Child's method1()
Devendra Lattu
  • 2,732
  • 2
  • 18
  • 27
  • Thank you! Your example made it clear. When the problem was given, I was expecting similar rule as 'run-time polymorphism' even though I knew it is not overridden case, because there seemed to be no clue which method1 is to be called from method2. I guess Java takes whichever is visible from the current class type. – GrinNare Apr 19 '17 at 03:45
  • 1
    If you want to work more on it, and understand more on how it works, you can simply click the method name in Eclipse and have a look at the method being highlighted (compile-time polymorphism). Then check the output which will tell you which method was called (run-time polymorphism) – Devendra Lattu Apr 19 '17 at 03:48
1

private methods and fields are not inherited. protected is the access modifier you were thinking of. In your post, the methods are not related (apart from having the same name).

protected void method1() {
    System.out.println ( "Parent's method1()" ); 
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • Yes, I'm aware of that the method1 in parent and child are not related. However, how does java figure out to call parent's method1? The actual type of the object is child, not parent. – GrinNare Apr 19 '17 at 03:31
  • 1
    Because `method2` is in `Parent` it has visibility to `method1` in `Parent`. Again, if you made `method1` `protected` it would be overriden by the method in `Child`. – Elliott Frisch Apr 19 '17 at 03:32
  • What I was trying to know is if there's a rule such as in overridden case. If a method is overridden, actual type decides which method is to be called. However, if a method is overloaded (like in this case... don't think this is overloading but anyways...) visibility takes priority. Am I right? – GrinNare Apr 19 '17 at 03:38
  • There is no overridden case with `private` methods, since they are not inherited. – Elliott Frisch Apr 19 '17 at 03:41