2

The output of this simple program is This is base.

public class mainApp{
    private void func(){
      System.out.println("This is base"); 
    }

    public static void main(String[] args){
        mainApp newObj = new derived();
        newObj.func();
    }
}

class derived extends mainApp{
    public void func(){ 
      System.out.println("This is derived"); 
    }
}
  • My question is when we are using this line mainApp newObj = new derived(); are we not actually creating an object of derived class using a reference of base class mainApp. So, when I am using the object to call it's method why don't I get the method from the derived class? Why I get the method from the base class.

  • using this line, mainApp newObj = new derived();, are we working with a reference of mainApp OR we are working with an object of derived class. Which one is correct?

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
Quazi Irfan
  • 2,555
  • 5
  • 34
  • 69

2 Answers2

8

The reason that you're getting the base class method is that the base class version of func is declared private, and Java does not allow private methods to be overridden by subclasses. This means that if you extend a base class and by pure coincidence decide to name a private member function the same name as a private member function in the base class, you don't accidentally change the behavior of the base class's member functions. You are indeed working with an object of type derived, but because the reference is statically typed as a mainApp, calling func is interpreted as calling the private method func in mainApp rather than the public method func in derived. Changing the code to read

derived d = new derived();
d.func();

fixes this, because the static type of d is now derived and the call to func has a different meaning.

At the JVM bytecode level, the instruction used to call private member functions is invokespecial whereas the instruction used to call normal, override-able member functions is invokevirtual. The two have totally different semantics; invokespecial begins looking in the current class (or some base class for things like constructors), whereas invokevirtual looks in the class corresponding to the object's type at runtime.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • Wow, excellent answer and you beat me to the punch. @iamcreasy a bit of reading for you on [Java and Polymorphism](http://home.cogeco.ca/~ve3ll/jatutor5.htm) to hopefully clear the shroud of confusion regarding your issue. – Grambot Jul 21 '11 at 21:14
  • I'm not used to the distinction between static and dynamic types coming up in Java! I actually was pretty surprised when I saw this. Good thing I learned C++ first. :-) – templatetypedef Jul 21 '11 at 21:15
  • @templatetypedef So, when I will be using dot notation after any reference, I will be using the methods of that particular reference regardless to the object the reference is pointing to. Is it correct? & what means "reference is statically typed"? – Quazi Irfan Jul 21 '11 at 21:21
  • 1
    @iamcreasy- **No**, that is incorrect. The code you've posted is a subtle edge case of how Java normally works. When you use a dot to select a method of a class, the behavior is as follows. If the method you're referring to is `private`, then the member function selected is the member function in the class of the type of the reference. In this case, since the reference has type `mainApp`, this calls the `mainApp` version of the method even though in `derived` there is another method with the same name. If the method you name is `public`, (continued...) – templatetypedef Jul 21 '11 at 21:23
  • 1
    @iamcreasy ...then the method invoked is the method contained in the object at runtime. If you change `func` from `private` to `public` in `mainApp`, then this call would call `derived`'s version of `func`, since the reference actually refers to a `derived` at runtime. Does this make sense? Or is there something else I can clarify? – templatetypedef Jul 21 '11 at 21:24
  • @templatetypedef That makes a lot of sense.It feels some sort of a priority list.Look for it, if found pick it, if not then go to next one, if found pick it, if not.... :) One more thing, *what means by "reference is statically typed"*. Any reading on statically typed and dynamically typed reference will do. – Quazi Irfan Jul 21 '11 at 21:31
  • 1
    @iamcreasy- The **static** type of an object is the type that you give it in the actual source file. If you have a reference of type `Object`, no matter what the reference refers to, it has static type `Object`. The **dynamic** type of an object is the type that it has at some particular point in the program while it's running. So in your code, the reference `newObj` has static type `mainApp`, but its dynamic type is `derived` because when the program is running, that's what it refers to. – templatetypedef Jul 21 '11 at 21:33
  • @templatetypedef What to do if I want `newObj.func();` to call the derived class's function, without removing something from the code? – Quazi Irfan Jul 21 '11 at 21:59
  • 1
    @iamcreasy- You'd have to put in a downcast, such as `((derived)newObj).func()`. If you do this, then the static type of `((derived)newObj)` is `derived`, so `func` refers to the function declared in `derived` instead of the one in `mainApp`. – templatetypedef Jul 21 '11 at 22:03
  • @templatetypedef I guess there is a priority between `the reference` and `the object it is pointing to`, about whose interface the user is gonna get depending on the scope of use. Is it? I just want to make sure I am not making any assumptions. – Quazi Irfan Jul 21 '11 at 22:08
  • 1
    @iamcreasy- Not quite. The process works something like this. First, the **static type** of the reference is looked at to determine what class to start out in. If the method in that class is `public`, then the method that's chosen is the method corresponding to the **dynamic** type (the method for the object actually being pointed at). If the method in that class is `private`, then the method that's chosen is the one found in the class for the **static** type. Does that clarify things a bit? This almost never comes up; it's only when a derived class tries overriding a private method. – templatetypedef Jul 21 '11 at 22:12
  • @templatetypedef Yeh, getting a clearer view now. But, a detailed discussion would be great read for me. Do you know any web reference or book that goes really deep on this? Googled some but no luck and books just skimmed over things like this. – Quazi Irfan Jul 21 '11 at 22:21
  • @iamcreasy- Unfortunately, I don't know anything like this off the top of my head. Most of the good discussions for things like this would be for other languages like C++ where these concerns come up more regularly. Sorry. :-( – templatetypedef Jul 21 '11 at 22:26
0

You are working with the derived class. The reference to that object is a the mainApp. Which means others see it as a mainApp but it is implemented as the derived class.

Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123