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 learning how to make your life as a programmer much easier by writing flexible and reusable code through interfaces and polymorphism.

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.

Because of the support code for this lab, it is very important to follow the directions in the stencil and in the CheckPoints! Name methods in the exact way asked for and instantiate in the order we state.

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). Open these up in sublime.

    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.
    1. It should take in a java.awt.Color as a parameter.
    2. It should not return anything.
    3. 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.

    4. 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 based on 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 there.
  5. 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? (Think inheritance).

  6. Save, 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 paint(...) method in your Incredibles class (Incredibles.java) to color in its components. Save!
  2. Write a paintIncredibles(...) method in the PaintShop class (PaintShop.java). 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.

This 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 to paint all paintable objects? The issue 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 classes inherit from a superclass PaintObject that can be painted. This way, we could write our paint method as paintThing(PaintObject paintObject) and the method could accept any subclass of PaintObject as an actual parameter.

However, there are a few problems with this design. Firstly, since Java classes can only inherit from a maximum of one class, if a class is the subclass of PaintObject, then it cannot be the subclass of anything else. This is the exact situation we are in. The Car and Incredibles classes already extend from another class (see extends in the class definition!), 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.