Jose Sandoval Google
 Resume     Book     Software     Drawings     Home     Subscribe to RSS feed Search Web Search josesandoval.com

Polymorphic overriding
Thursday, January 06, 2005

Explaining polymorphism seems to be quite a task. Understanding it is not a walk in the park, either. But, when you get it, you just get it. It's similar to recursion, or, the dreaded, pointers in C.

I thought I'd give it a shot and decided to write this little tutorial. It is composed of 3 sections: UML diagram, English explanation, and code sample.

It is interesting to note that trying to explain one of the pillars of OO theory, you must make use of the other two: in order to explain polymorphism, inheritance and encapsulation must be used. I wonder, if you can make this fact an actual theorem?

UML

Polymorphism: Main is in charge of Stadium - Note that Stadium doesn't care of the type of player - It only cares that it is a sport.


English description
  1. If you are participating in any type of Sport, you are likely to play something.
  2. Any SportPlayer plays, via the play() method.
  3. Almost all sports need some kind of equipment. Thus, the method getReadyToPlay() is available to anyone who is a SportPlayer and needs to put on equipment.

    Note that a SportPlayer doesn't know how to play yet: play() is still an empty stub. You can think of this state as someone who is a player, who hasn't learnt how to actually play.

  4. A SoccerPlayer is a type of SportPlayer, and knows how to actually play - It overrides the play() method.
  5. Similarly a BaseballPlayer is a SportPlayer and knows how to play baseball.

    Note that SoccerPlayer and BaseballPlayer don't directly implement the Sport interface's play() method. They are in fact overriding play(), which ultimately is a type of polymorphism (There are other kinds). These classes actually extend SportPlayer, as each player type (soccer or baseball) sometimes need to get ready before playing.

  6. Almost any sport can be played inside a stadium. As players arrive, they go inside the stadium and present themselves as SoccerPlayer and BaseballPlayer.
  7. Since, what they practice is a Sport type, then the stadium knows what to do with such items: allow them to play the sport.

    The SoccerPlayer and BaseballPlayer need to be told when to play. I.e. when the field is empty for each sport - Thus, it queues each player as it arrives, and later tells them to play.
How does the Stadium object know how to call each respective play() method?

It seems like magic, doesn't it? We owe the trick to polymorphism or late binding.

The Java JVM knows how to look up which implementation of the play() method to run, at run time (pun intended).

Again, if you notice, SportPlayer actually implemented play() first, however, each player overrides the parent play() method and is not directly implementing play() from Sport.

Something else to take note of is the fact that SoccerPlayer and BaseballPlayer are SportPlayer types, and they are also of type Sport. Java doesn't have multiple inheritance, but, there is nothing stopping you from faking it.

And why not have SoccerPlayer and BaseballPlayer implement Sport directly? Again, each player needs to know how to getReadyToPlay() if needed. Whatever getting ready means. I.e. For soccer, put soccer shoes on, chin pads, et al.

Talking about soccer: at the place where I'm currently contracting, a few of the employees put together a soccer team to participate in a semi-competitive indoor soccer league. There are different categories: A being the group with the more completive teams and league B, with the semi-competitive teams and C, where everyone just goes to enjoy a game. Anyway, I was asked to participate and yesterday we had the finals of the season. We won the championship with a record of all wins and no losses.

Code sample
//The interface
interface Sport {
    public void play();
}

// SportPlayer implementing Sport
class SportPlayer implements Sport {
    // Getting equipment on
    // Common to all sports
        protected void getReadyToPlay() {
        System.out.println("Put shoes on.");
    }

    // Dummy play
    public void play() {
        // Empty
    }
}

// SoccerPlayer extends SportPlayer and becomes
// of type SportPlayer and Sport
class SoccerPlayer extends SportPlayer {
    public void play() {
        System.out.println("-----------------------");
    getReadyToPlay();
        System.out.println("Playing soccer: kicking.");
        System.out.println("-----------------------");
    }
}

// BaseballPlayer extends SportPlayer and becomes
// of type SportPlayer and Sport
class BaseballPlayer extends SportPlayer {
    public void play() {
        System.out.println("-----------------------");
        getReadyToPlay();
        System.out.println("Playing baseball: batting.");
        System.out.println("-----------------------");
    }
}

// This is where everyone plays
class Stadium {
    public void playBall(Sport object) {
        object.play();
    }
}

// The Main class
public class Main {
    public static void main(String[] args) {
        // Everyone gathers at the stadium
        // to play some kind of sport.
        Stadium stadium = new Stadium();
        Sport[] sport = {new SoccerPlayer(),
                    new BaseballPlayer()};

        for (int i = 0; i<sport.length; i++) {
            stadium.playBall(sport[i]);
        }
    }
}


Running the program, you get the following output:
    C:\jose\java\polymorphism>java Main
    --------------------------------
    Put shoes on.
    Playing soccer: kicking the ball.
    --------------------------------
    --------------------------------
    Put shoes on.
    Playing baseball: batting the ball.
    --------------------------------


8:57 PM | 2 comment(s) |

Comments:

You don't need to introduce inheritance or encapsulation to explain polymorphism. There are lots of languages in which classes can be used polymorphically without being related by inheritance. There are also languages that do not enforce encapsulation but expect programmers to "do the right thing" by convention. Python is an example of a language that has polymorphism without needing inheritance or encapsulation.
By Anonymous Anonymous, at 4:08 AM


Encapsulation may not 100% required. Encapsulation is just hiding the implementation of something. That's a debateable point.

However, I don't see how it would work without inheritance, for any OO language. At least not in Java, which is the example.

I've seen python, but, I have not played around with it for me to make any educated comment on it. Though, so I'm not convinced that you don't need inheritance (in whaterver form) to acomplish polymorphism.

On that argument, you could also say that a "var" variable definition in JavaScript is also a polymorphic variable, as it can take any type of value and the program just "knows" what to do with it - Maybe there are a whole bunch of "ifs" somewhere checking what type it is - But, that's not OO. I think, however, that there is some inheritance somewhere in the JavaScript engine to accomplish this - Again, I've never seen code implementation of a JavaScript engine.



This page is powered by Blogger. Isn't yours?

Guestbook
© Jose Sandoval 2004-2009 jose@josesandoval.com