We will be practicing basic class inheritance in our lab for this week. You are
We will be practicing basic class inheritance in our lab for this week. You are going to create a simple hierarchy of classes based on shapes.
In addition to practicing basic inheritance, we will also be looking at elements that are commonly included in derived classes, such as super constructors, the protected access modifier, and method overriding. The goal for this lab is to recognize the power of class inheritance and its ability to create complex object types with simple instructions.
Construct the lab file by following the instructions below. The check-in for the lab this Friday will be for parts 1 and 2 below. Once you have completed the program, you will submit it for this assignment.
Part 1: Animal Class Hierarchy
Imagine you wanted to create a program for a zoo that contained a class for each type of animal the zoo could contain. This wouldn’t just be for generic types of animals, but for specific species of animal such as brown bear, polar bear, black bear, panda bear, etc. That would be a lot of classes! More importantly than that, many of those classes would have very similar functionality – each of the bear classes are probably very similar to one another. This quickly turns into a headache of having to copy and paste redundant code many times – and worse, if you need to make a change to the bears later then you have to go back and change every single bear class.
This is the very problem that class inheritance was designed to solve. We can make one class that contains functionality that should be shared by other classes, and then we can have all of those classes “inherit” that code directly from the shared file. For this program, we are going to define a suite of short classes for different animals and use inheritance to save us the trouble of writing redundant code.
Follow along with the video to construct the classes that you will need for this lab. The code for the classes created in the video is provided below, but you are encouraged to follow along and create them yourself for practice. After you have finished watching the video, continue with the instructions below.
Files from the video:
Once you have been introduced to the lab concept from the video, proceed with the following.
Create two new animal classes that fit into this existing project. You can extend the classes that are already there to create specific species of animals, or you can define new classifications such as Mammal or Reptile. These two classes must adhere to the following rules:
All classes must directly or indirectly inherit from the Animal class.
The classes you create must inherit from the existing classes in a logical way: for example, do not create an Eagle class and have it inherit from Fish.
Each class you create must contain a new variable that is not inherited from other classes, as well as some kind of accessor/mutator methods for that variable.
The constructors for the classes you create must set the variables appropriately. You may hard-code in values like the video showed.
You must override the makeNoise method for each class you create if it makes sense to.
Part 2: UML Class Diagram
The zoo project in part 1 is made up of a lot of different classes with their own methods and classes. To prevent this project from becoming too complicated, we will create a UML class diagram to model each class and their relationships to one another.
Create a UML class diagram for all of the classes from part 1 (including the two you designed yourself) showing the full details of each class’s members and their inheritance relationships.
Modeling inheritance on a UML class diagram is relatively easy and only involves a few extra details that weren’t covered in the original UML chapter:
Inheritance relationships are shown as a solid line with an empty/white arrow pointing to the parent class. The convention is to always have the parent class above its child classes so that inheritance relationships are shown vertically. Inheritance relationship lines don’t need role descriptions or multiplicity values.
Class members with protected access use the symbol # (instead of + for public or – for private).
If a variable or method is inherited directly by a child class, then it does not need to be included in the child class’s box. The inheritance of those class members is implied by the relationship arrow.
If a child class overrides a method from a parent class, then that method must be included in the child class’s box. You can tell that it’s an overridden method and not just an inherited one because the same method appears in both the child and parent classes.
This is the minimum amount of progress on the program that is required for this week’s check-in. Please make your check-in post now before continuing with the remainder of the lab. Please remember to make the check-in post before the deadline.
Part 3: Geometric Shapes
Another great demonstration of inheritance is in the types of geometric shapes. There are different classifications for the various 2D shapes in mathematics, but certain classifications are just more specific versions of others.
For this part of the lab you will be creating a suite of short classes for a variety of geometric 2D shapes:
Polygon: any 2D shape made up of any number of straight sidesTriangle: any polygon with exactly 3 sides
Quadrilateral: any polygon with exactly 4 sidesParallelogram: any quadrilateral where opposite sides are equal lengthRhombus: any parallelogram where all sides are the same length
Rectangle: any parallelogram where the interior angles of the shape are all 90 degreesSquare: any rectangle where all sides are the same length
(Note: you can also define a square as a rhombus where the interior angles are all 90 degrees)
The video below explains the relationships between the shapes
For this part of the lab, follow the instructions below to create the shape classes that inherit from one another.
Polygon
The Polygon class needs to be able to keep track of a shape with any number of sides. Since this is also the root class that all of our other classes will inherit from, it is also going to contain a little bit of functionality that all shape classes should share.
Add the following variable and methods to the Polygon class.
protected int[] sidesThe array that represents the sides of the shape. Each integer in the array is the length of one side. This array should not have a default length! Polygons can have any number of sides, so the array should be custom-made for each polygon for its needs.
public Polygon(int[] sides)The constructor for a Polygon. It should just set the sides variable to the array parameter.
public int findPerimeter()Returns the perimeter of the polygon. This is the sum of the lengths of all sides.
Triangle
The triangle class inherits from Polygon. This class should only contain the constructor for Triangles.
The constructor should be made in such a way that it prevents Triangles from having anything other than 3 sides. This constructor needs to call the Polygon super constructor, but that does not mean that this constructor needs to be the same as the super constructor. Copy the constructor below into Triangle.
public Triangle(int side1, int side2, int side3) {
super(new int[3]);
sides[0] = side1;
sides[1] = side2;
sides[2] = side3;
}This constructor first passes an empty array of length 3 to the super constructor. This constructs a Polygon of 3 sides, which is what a Triangle is. Then we set the lengths of the 3 sides based on the parameters.
Quadrilateral
The Quadrilateral class also inherits from Polygon. This class should also only contain a constructor.
Define the Quadrilateral constructor in the same manner as the Triangle constructor, except for 4 sides instead of 3. This way we know that all Quadrilaterals and any classes that inherit from Quadrilateral always have exactly 4 sides.
Parallelogram
The Parallelogram class inherits from Quadrilateral. This class needs to modify the constructor even further to enforce the rule that opposite sides of a parallelogram are always equal length. It is also going to add some new functionality that will be useful for any derived classes.
Add the following variable and methods to the Parallelogram class:
int interiorAngle;The measurement of one interior angle of the Parallelogram, in degrees. The way Quadrilaterals are defined, there are always two pairs of equal angles in the Quadrilateral. This means we’re missing the measurement of the other angle, but thankfully we can calculate it on the fly: it will always be 180 minus our other angle.
public Parallelogram(int side1, int side2, int angle)The constructor for Parallelograms. Since opposite sides of parallelograms are always equal, we only need two side measurements. But the super constructor requires 4 sides, so what do we do? We can pass in the side measurements as pairs like this:
super(side1, side2, side1, side2);
This ensures that our four sides are always two pairs of equal sides. Also don’t forget to set the lengths of the sides and the interiorAngle variable!
public void printArea()This method prints out the area of the Parallelogram. Copy the following code for this method:
double area = sides[0] * sides[1] * Math.sin(Math.toRadians(interiorAngle));System.out.println(“Area is ” + area + “; found using Parallelogram’s method”);
You find the area of a parallelogram by multiplying the two side lengths by the sine of any interior angle (hence why we need to store the interior angle as a variable). We’ve stored the interior angle in degrees, but the sin method uses radians, so we’ll have to convert the number using the toRadians method first. We state that we’re using Parallelogram’s method for the printing because we’re planning on overwriting it in a derived class, and we want to see which class’s method is being called.
Rhombus
The Rhombus class inherits from Parallelogram. This class should only contain a constructor.
The Rhombus constructor should look like this:
public Rhombus(int side, int angle) {
super(side, side, angle);
}This is the same principle we used in Parallelogram to force opposite sides to be equal. Since all sides on a rhombus are equal, we only need one side measurement. We then pass it to both parameters of the super constructor, which is for Parallelogram (we also pass the angle so it is set correctly in that constructor). The Parallelogram class then turns those two equal side measurements into four equal side measurements for Quadrilateral, which in turn creates the array and sends it to Polygon. All of this together means that for very little code we can ensure that all Rhombuses always have 4 equal sides.
Rectangle
The Rectangle class inherits from Parallelogram. This class should contain a constructor, and it should override the printArea method that it inherits from Parallelogram.
The constructor should only take 2 side length parameters. When it calls the super constructor, it should pass those two parameters and then the number 90. By hard-coding in the number 90, we ensure that when the super constructor (Parallelogram’s) is called, the interiorAngle variable is always set to 90. That way we enforce the rule that rectangles are like parallelograms but with a 90 degree interior angle.
We are also going to override the printArea method in this class. The parallelogram’s area calculation will work for rectangles, but it is inefficient – to find the area of a rectangle we just need to multiply the two sides together (we can exclude the sine). The overridden method should look like this:
@Override
public void printArea() {
double area = sides[0] * sides[1];
System.out.println(“Area is ” + area + “; found using Rectangle’s method”);
}We also specify which class’s method we are using here. Now whenever we call the printArea method we know which class is providing the calculations, Parallelogram or Rectangle.
Square
The Square class inherits from Rectangle (it could also inherit from Rhombus, but Rectangle is easier for this program). This class should only contain a constructor.
Create the Square class’s constructor in the same manner as the Rhombus constructor, except without specifying the interior angle. It should only have one parameter: the side length.
Although our constructors started with many parameters, we have now narrowed it down to 1. Each constructor only takes the parameters it needs and manipulates the super constructors into creating the rest of the information necessary for that shape. Squares take one side length (since all of their sides are equal). The super constructor, Rectangle, takes that side length twice to use for its pairs of equal sides. The next super constructor, Parallelogram, takes those two side pair lengths and also an interior angle measurement that Rectangle always provides as 90. This goes to the next super constructor, Quadrilateral, which takes four side lengths, the two side pair lengths of Parallelogram doubled (which means Square’s original side length has now been duplicated to all 4 sides). Finally, the super constructor for Polygon is called and passed an array of length 4, which is filled inside of Quadrilateral.
Main Method
Create a main method inside of the Parallelogram class with the following code:
Create a Rhombus with side length 2 and any angle.
Call the printArea method on the Rhombus.
Create a Square with side length 4.
Call the printArea method on the Square.
After you create the main method, run the program and take a screenshot of the main method’s output.
Submission
For this lab you will be submitting 3 files:
The UML class diagram created in part 2 for the zoo classes
The Parallelogram.java class file from part 3, which also contains the code for the main method
The screenshot of your program’s output after running the main method from part 3
Submit your files by clicking “Start Assignment” at the top of the page and then selecting your files for submission. You can submit all files by selecting “Add Another File” in the submission box. Please submit all files individually; this assignment will NOT accept a zip file or an Eclipse project.
Leave a Reply