Interfaces and Polymorphism

We've had four weeks of CS15 and by now, the buzz words of Object-Oriented Programming (OOP) should be familiar to you. OOP is an extremely powerful and quickly growing modeling paradigm making programming large scale applications much easier than before. For the remainder of the course, a good understating of OOP concepts will be integral to designing and implementing the assignments. This lab is about how to make your life as a programmer much easier by teaching you how to write flexible and reusable code through interfaces and making polymorphism your best friend.

Goal: Learn how to implement polymorphism using interfaces.

Life before polymorphism, sigh...

Let's say you are running a little low on funds, and decided to earn some money, and exercise your creative muscles at the same time, by opening a car painting business! Since you are a very savvy programmer, you're going to write a program that will do the painting for you.

You'll begin by finding cars that need to be painted.

Check Point 1

  1. Run cs015_install labInterPoly to get the stencil for this lab. (You should have the following files in your directory: App.java, PaintShop.java, Car.java, Fish.java, and Incredibles.java).

    We'll concentrate on the Car.java file for now. The Car has the following components:

    • roof
    • body
    • door
    • hood
  2. Add a paint(...) method to the Car class that takes a java.awt.Color as a parameter. Inside this method you will want to set the color of the Car's components listed above. Each component has a setColor(...) method that takes a java.awt.Color as a parameter. Click "Save" to save the code you added to the Car class.
  3. Compile your code to make sure there are no errors!



Now that we have a car, let's figure out how to paint it!

Check Point 2

  1. Add an instance variable to the PaintShop.java to store the current color.
  2. Create an accessor method and mutator method for the current color instance variable. This should be a piece of cake after LiteBrite.
  3. Add a paintCar(...) method to the PaintShop
    1. It should take in a Car as a parameter.
    2. It should not return anything.
    3. It should paint the Car that was passed in the "current color".
      1. HINT: use the Car's paint(...) method

      (Remember to save!)

  4. Test what you've done by instantiating a Car object in the constructor of App.java. An instance of PaintShop should already be created. In order for the PaintShop to "know about" the car (i.e. to set up an association with the car), use the PaintShop's add(...) method and pass it the car you've just created. (Question: where is this add(...) method defined?) Save!
  5. Compile and run the application. (run with: java labInterPoly.App) You can paint the Car different colors by selecting a color from the Color Chooser and then clicking on the car.

Your painting business became very successful and you want to expand your business to paint other things like: walls, roads, tables, chairs, beds, ceilings, squares, circles, and everything else in the world that can be painted. Yes, it seems ambitious, but with Java at your side anything is possible!

Your new customers request that you paint some superheroes.

Check Point 3

HINT: This is very, very similar to what you did above.

  1. Write a paintIncredibles(...) method in the PaintShop class (PaintShop.java). Save!
  2. Write a paint(...) method in your Incredibles class (Incredibles.java) to color in its components. Save!
  3. Instantiate an instance of Incredibles in the constructor for App and add it to the PaintShop (just like you did with the Car instance). Save!
  4. Compile and run the application. You can control which item you are painting using the radio buttons at the top.

There are a lot of very similar methods that you have to write for all the things that can be painted. The design so far has a serious problem. Your PaintShop class is very spiffy, and you want everyone to benefit from your hard work. The only problem is, every time someone wants to paint something new, you are going to have to add a new paintThing(...) method in the PaintShop class to paint the new item. If someone wanted to paint a door, you would need to add a paintDoor(...) method, if someone wanted to paint a house, you would need to add a paintHouse(...) method...and you get the idea.

Wouldn't it be nice to just have one method that can paint anything that can be painted? It seems like a fairly simple concept, but the trick is that the PaintShop's paintThing(...) method takes in a parameter: the object it is supposed to paint. For paintCar(...) it took in a car, for paintIncredibles(...), it took in an instance of the Incredibles. What type should it be for the generic version? Tricky, tricky, tricky...

One way to do it would be to have some superclass that can be painted and create subclasses that inherit from this superclass for all the objects that you want to paint. This is called inheritance. However, there are a few problems with that design. Firstly, since each class can only inherit from one class at a time, if a class is the subclass of a Paint class, then it cannot be the subclass of anything else. This is the exact situation we are in. The Car and Incredibles classes already extend cs015.labs.PaintShop.DisplayObject, so they can't be the subclass of anything else. Secondly, the relationship between the different subclasses is a weak one; the only thing they have in common is that they can be painted. Using inheritance here would be limiting and unnecessary.