Build three classes that inherit from an existing Shape superclass. These subclasses should all have the phrase “extends Shape” in their class signatures, as in: “public class MyNewShape extends Shape {“. Your classes can and should be tested in isolation before combining your classes with the final drivers, so consider building a main in each subclass that tests out just that class. When you are confident in your subclasses, you can use this driver to see your shapes render to a JPanel. Note that this is also the driver which I will use when grading your work, so you should be sure to verify that these classes play well together.
In the previous assignments, we were practicing new and review concepts. This assignment is the first in which we’ll explore the idea of inheritance, which is critical theme in object-oriented programming.
Inheritance as defined in the software realm borrows from its genetic counterpart; just as you can inherit your mother’s eyes or your father’s sense of humor, one child class can inherit characteristics and behaviours of a parent class. More specifically to Java classes, when one child class inherits from a parent class (or a subclass inherits from a superclass), this child class gets a copy of all the methods and data from the parent class – you can envision this as a copy-and-paste operation, from the parent to the child. Once the child class extends the parent class, any methods or data items found in the parent class are now a part of the child class, and the child class is free to define extra features. In Venn diagram terms, the parent class is strictly a subset of the child class, and would look like:
What this picture highlights is the relationship between parent classes and child classes – everything the parent class has, the child also has. More to the point: any public method defined in the parent will also be defined in the child class, and this acts as a type of guarantee. If we can promise that a Circle class has every method found in the Shape class, then anywhere in software a Shape is called for, a Circle could be substituted (this concept is called substitutability and is related to polymorphism, but more on that later). If we have a function that expects a Ball object, and we have a subclass object VolleyBall, then we can pass the VolleyBall to the method with no problems, because a VolleyBall is a Ball, just like a Circle is a Shape. Inheritance then defines this type of “is a” relationship, which is a one-way relation between two classes. Note that the relationship isn’t like the biconditional operator in that, all VolleyBalls are definitely Balls, but not all Balls are guaranteed to be VolleyBalls (some could be BaseBalls or BasketBalls, for example). When describing inheritance relationships, we’ll use an arrow to indicate this “one-way” characteristic. When building classes that are interrelated via inheritance, inheritance hierarchies naturally arise; these are simply tree structures that display the “is a” inheritance relationships between the classes in your software.
Before we talk about the methods your Class must provide (or more specifically, override), we should get to know our Parent class Shape. The methods and data for this class are outlined below, and the code is available for download via the website (and you’ll need it in the same directory as your child classes).
Data
· int x; //all shapes have an x,y coordinate pair in Java2D
· int y; //and so we’ll have the Parent class manage this data
Methods
· Shape(int x, int y) //a constructor used to initialize the data members
· double getArea(); //used to calculate the area of this shape
· void paint(Graphics g); //the paint method is called on each shape to draw itself
· getX() //accessor
· getY() //accessor
· setX(int) //mutator
· setY(int) //mutator
As you can see from above, the class is quite small. Now take a look in the code to see how many of the Shape functions are actually empty! Shape is really too generic of a class to offer an implementation for draw() or getArea(), as these are custom to specific subclasses of shape – in fact, it’s our job to provide versions of these methods in our subclass that actually do draw shapes or calculate areas. Your class will start with the line “public Circle extends Shape”, and this will only compile if Shape.java is also in the same directory (or project) when compiling. As a Circle, you will need to add more data and methods that are custom to being a circle; these are specifics that not just any shape would have, such as a radius data item and a getRadius() accessor function.
The first thing we need to do is download the Shape superclass, the Spray subclass, and the driver PolyDemo.java. This should compile and run with no modifications, but will only display a set of “spray” shapes on the screen (which are ovals that randomly change their width and height). You will extend this code by:
(1) Building subclasses that, like the Spray class, extend Shape (all files in the same directory)
(2) Implementing and overriding the important methods for those subclasses
a. Draw needs an implementation
b. getArea needs an implementation
c. Your class may define additional data or methods, just like a Circle would define an additional data member to represent its radius
(3) Modifying the PolyDemo function getRandShape() so that it can create and return objects of your new Shape subclass.
By following the three steps above, you should be able to iteratively develop each Shape subclass and test it first in isolation (make a small main inside that class to test it out), and then in the larger system that will use your subclass to actually draw stuff to the screen.
This is the part of the assignment that has the least constraints on it. You are to develop a shape subclass, and you can draw it however you want using Java2D. Java uses a Graphics2D object to render things into drawable areas in Java’s windows (or JFrames). We won’t need to go much further than a google search to see all the functions you can call on a Graphics2D object, but some of them are: {drawRect, drawRoundRect, drawFillRect, drawOval, drawString} You could make a Shape subclass that represents a letter, and to draw that letter, you’d provide a line of code in your draw() method like “g.drawString(…)” to draw the individual character. If making ovals, use the drawOval function, and the same strategy for rectangles. While the text is a bit light on the subject of Graphics, it does cover some data on drawing ovals and arcs on page 1033, and also shows you how to specify colors on page 1045. DrawString is at 1051, and again, there are tons of examples online for Java2D graphics code, but the main idea is: you are given a graphics object, and you make calls on that object to produce graphics you can view on the screen. Note that we will walk over an example Square class in class before the assignment is due, and I’ll demonstrate some of the things you can do with a graphics object. In eclipse, if you simply type “g.”, then the list of graphics functions will be highlighted for you, and there’s a ton, so don’t get overwhelmed. If you like, you can just leave the draw function very minimal until you have a grasp on how your class inherits from Shape, and how it fits into the driver code.
· Square will be demonstrated in class, and you can build a Square subclass if you wish, but of the three classes you have to turn in, you cannot submit a Square.
· Be sure to document your code with comments!
· Consider waiting until I cover inheritance in the next lecture before starting coding, as I will give you an additional shape (Square).