Static and Dynamic Binding in Java

502 views Asked by At

Please can someone explain to me how the last 6 lines of the output get printed. I know that due to static binding the first three lines are printed appropriately.

I do not know why the 5th line gives the output because it is of type Ipod and it does not have any method for song but still it prints the output. Here is the code:

package myferrari;

import mycar.*;

class IPOD
{
    void PlayMusic(Music m)
    {
        System.out.println("Music from Ipod");
    }
}

class IpodPlayer extends IPOD
{
    void PlayMusic(Music m)
    {
        System.out.println("Music from IpodPlayer");
    }

    void PlayMusic(Song m)
    {
        System.out.println("Song from IpodPlayer");
    }
}

class Music{}
class Song extends Music{}

public class Main  {

    public static void main(String [] args)
    {
        IPOD ipod = new IPOD();
        IpodPlayer iplayer = new IpodPlayer();
        IPOD ipl = new IpodPlayer();

        Music m = new Music();
        Song s = new Song();
        Music sm = new Song();

        iplayer.PlayMusic(m);
        iplayer.PlayMusic(s);
        iplayer.PlayMusic(sm);  // static binding refers to the reference type

        ipod.PlayMusic(m);      
        ipod.PlayMusic(s);
        ipod.PlayMusic(sm);

        ipl.PlayMusic(m);
        ipl.PlayMusic(s);
        ipl.PlayMusic(sm);

    }
}

The output is here:

Music from IpodPlayer
Song from IpodPlayer
Music from IpodPlayer
Music from Ipod
Music from Ipod
Music from Ipod
Music from IpodPlayer
Music from IpodPlayer
Music from IpodPlayer
4

There are 4 answers

0
hagrawal7777 On BEST ANSWER

Nut shell: Whole concept is about method overloading and overriding and how they are linked with dynamic and static binding.

Now, first of all see below snippet which is simplification of your case @run-time and understand the run-time picture. Debug your code using any IDE of your choice and you will see exactly same result.

Major take-away: At run-time your reference will resolve to the actual object, this is called as Dynamic binding or polymorphism. Run-time means object. So, whether IpodPlayer iplayer = new IpodPlayer(); OR IPOD ipl = new IpodPlayer();, at run-time you will get instance of IpodPlayer and its method would be called.

Dynamic binding in linked with method overriding. So, at run-time which overridden method will be called is decided by checking the object type. So, you can see that whatever be the reference type, at run-time PlayMusic method of actual object is called.

This sums up your dynamic binding and method overriding.

    new IpodPlayer().PlayMusic(new Music());        //Music from IpodPlayer 
    new IpodPlayer().PlayMusic(new Song());         //Song from IpodPlayer 
    new IpodPlayer().PlayMusic(new Song());         //Music from IpodPlayer 

    new IPOD().PlayMusic(new Music());              //Music from Ipod     
    new IPOD().PlayMusic(new Song());               //Music from Ipod 
    new IPOD().PlayMusic(new Song());               //Music from Ipod 

    new IpodPlayer().PlayMusic(new Music());        //Music from IpodPlayer 
    new IpodPlayer().PlayMusic(new Song());         //Music from IpodPlayer 
    new IpodPlayer().PlayMusic(new Song());         //Music from IpodPlayer

Coming to static binding and method overloading.

Static binding clear things on how overloaded methods in java are bonded during compile time using Type information.

Now, your case of IPOD ipod = new IPOD(); is very clear, since you have only method and no overloaded method so your result no. 4,5 and 6 are self explanatory.

Real confusion is in case of IpodPlayer iplayer = new IpodPlayer(); AND IPOD ipl = new IpodPlayer();.

At compile time it is decided that which overload method will be called based on object type, whether PlayMusic(Music m) or PlayMusic(Song m). Please note, I am talking only about method and not which class or object..

Now, in your case no. 1,2 and 3, since the object the of new IpodPlayer() and you have two overloaded method so appropriate PlayMusic method is called, based on object type of PlayMusic

Last cases - your case no. 7, 8 and 9 which is major head scratching cases and most important to understand because it combines concept of dynamic binding as well as static binding.
Again at compile time which overloaded method to be called is decided based on object type but since at compile time it is deciding based on the IPOD ipl and not = new IpodPlayer();, so compiler decides and generates the byte code that PlayMusic(Music m) will get called at run-time (which ever object's method but PlayMusic(Music m) method) because IPOD doesn't have any other method. And finally at run-time dynamic binding will come into picture and method of IpodPlayer will be called because of = new IpodPlayer();

0
Dustin Wells On

Your class that does the printing has a method that takes the object in as a Music class, not the subclass of Song.

In order to do what you are wanting, you would have to do as follows:

void PlayMusic(Music m){
  if(m instance of Song){
    System.out.println("Song from Ipod");
  } else
    System.out.println("Music from Ipod");
}

and since you declared ipl as the super class IPOD and instantiated it as IPodPlayer, it behaves as IPOD unless you check it's type and cast it appropriately.

IpodPlayer player2 = null;
if(ipl instance of IpodPlayer)
    player2 = (IpodPlayer)ipl;

But that just doesn't make sense to do, so just use it as the class you want it to behave as.

This post explains it better than I can. Static Vs. Dynamic Binding in Java

0
AudioBubble On

The reason in that: At first java uses static binding in selecting from set of overloaded methods. And then dynamic binding in selecting from set of overrided methods. http://beginnersbook.com/2013/04/java-static-dynamic-binding/

class IpodPlayer extends IPOD
{
    //that is overriding
    void PlayMusic(Music m)
    {
        System.out.println("Music from IpodPlayer");
    }

    //that is overloading    
    void PlayMusic(Song m)
    {
        System.out.println("Song from IpodPlayer");
    }
}
2
A.sharif On

I take it that you understand why the first three lines are printed, so I won't explain the reasoning behind that.

So think of it like this. Whenever you"extends" to a class, you are essentially creating new a copy of that class and adding stuff to it. If you imagine a class as a blueprint to a house that holds rooms (methods) and appliances(variables) then a class that extends another class is a blueprint to a house that is based off another blueprint with some possible modifications/additions. When you're creating your blueprint that extends another blueprint, any room or appliance that you add that has the same signature(same name/type/arguments) as the something from the original blueprint, will overwrite that thing from the original blueprint.

Explanation why each of the lines print out like they do:

Line 4: You created an IPOD class, which only has one method and prints the same thing, "Music from Ipod".

Line 5:You created an IPOD class, which only has one method and prints the same thing, "Music from Ipod". Yes that method only accepts the Music type however Song extends The Music. Going back to the example: that means that the music house's rooms and appliances are inside of the song house. So since the method isn't looking for a song house, it removes everything that isn't part of the music house and throws it away. Then hands the music house to the method inside of the IPOD class.

Line 6: You created an IPOD class, which only has one method and prints the same thing, "Music from Ipod". SM is a music object so it is easily passed to the method.

Line 8: so the 8th line is made with these lines of code in your main:

IPOD ipl = new IpodPlayer();
Song s = new Song();
ipl.PlayMusic(s);

ipl is of class IPOD not IpodPlayer Class. There is no method for an Object Song in the IPOD class. When you write "IPOD ipl = new IpodPlayer();" you aren't creating an IpodPlayer object. You are creating an IPOD object. When you say "new IpodPlayer" in this context, you're essentially saying use the IpodPlayer blueprint to build an IPOD Object. An IPOD Object is a class with one method, "void PlayMusic(Music m)". So ipl will only have one method (the music method). The reason why it says "Music from IpodPlayer", instead of "Music from Ipod" is because you overrided the IPOD method with the IpodPlayer method with the same signiture (void PlayMusic(Music m)) when you used the IpodPlayer blueprint to build the IPOD object. This only works because the IpodPlayer is extending the IPOD class.

Line 7&9: IPL is an IPOD class however you overwrite the method named "PlayMusic" with the same named method from the IpodPlayer class during declaration. That's why m, s, and sm all print out "Music from IpodPlayer"