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.
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
Run
cs015_install labInterPolyto 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
- Add a
paint(...)method to theCarclass that takes ajava.awt.Coloras a parameter. Inside this method you will want to set the color of theCar's components listed above. Each component has asetColor(...)method that takes ajava.awt.Coloras a parameter. Click "Save" to save the code you added to theCarclass. - 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
- Add an instance variable to the
PaintShop.javato store the current color. - Create an accessor method and mutator method for the current color instance variable. This should be a piece of cake after LiteBrite.
- Add a
paintCar(...)method to thePaintShop - It should take in a
Caras a parameter. - It should not return anything.
- It should paint the
Carbased on the "current color".- HINT: use the
Car'spaint(...)method
(Remember to save!)
- HINT: use the
- Test what you've done by instantiating a
Carobject in the constructor of App.java. An instance ofPaintShopshould already be created. In order for thePaintShopto "know about" the car (i.e. to set up an association with the car), use thePaintShop'sadd(...)method and pass it the car you've just created. (Question: where is thisadd(...)method defined?) Save! - Compile and run the application. (run with:
java labInterPoly.App) You can paint theCardifferent 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.
- Write a
paint(...)method in yourIncrediblesclass (Incredibles.java) to color in its components. Save! - Write a
paintIncredibles(...)method in thePaintShopclass (PaintShop.java). Save! - Instantiate an instance of
Incrediblesin the constructor forAppand add it to thePaintShop(just like you did with theCarinstance). Save! - 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 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.