Colorado State University Logo | CS 163/4: Java Programming (CS 1) Colorado State University Logo | CS 163/4: Java Programming (CS 1)
CS 163/4: Java Programming (CS 1)
Computer Science

Lab 16 - Abstract Classes and Inheritance

Introduction

What are Abstract Classes? An Abstract class acts as a way to define methods and variables that can be inherited to form a specific relationship. Abstract classes are a powerful aspect of Object Oriented Programing, they allow us to define a single super class which has key traits necessary for multiple subclasses, but unlike normal inheritance an Abstract class by itself cannot be an Object. In addition to Abstract Classes we will also be discussing a close relative of Abstract Classes known as Interfaces, very similar to Abstract Classes but with a few key differences.

Abstract Class Use

The first part that makes Abstract Classes is how they are defined in code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
abstract class Shape {

   protected Point position;

   abstract double computeArea();

   public Point getPosition() {
      return this.position;
   }

   public void setPosition(Point position) {
      this.position = position;
   }

   public void movePositionRelative(Point position) {
      double x = this.position.getX() + position.getX();
      double y = this.position.getY() + position.getY();

      this.position.setX(x);
      this.position.setY(y);
   }
}

Abstract classes act as normal inheritance expect for one part, you may see that the computeArea() method has the word abstract before it. This tells the system that when you inherit from the Shape class you promise to complete any method labeled as abstract. This allows you to define methods needed by any class inheriting from your abstract class, but gives the subclass the task of completing the method in a way that makes sense for that subclass. For example lets say we have 3 subclasses inheriting from the above shape class, Circle, Square, Triangle. All 3 of these shapes have unique way of computing their area, pi*r^2, side^2, (1/2)*base*height, respectively. By making compute area abstract we force the user to define their own version of computerArea, potentially avoiding accidentally forgetting to define computeArea or trying to use values defined in shape that the subclass may not have access to. The purpose of an Abstract class is to build a base outline for a class which can include some lines of code and allows you to relate multiple subclasses together, something that will be focused on in a later lab.
So how do you define an Abstract class? The first step of an abstract class is its definition. The below shows the simple outline of an abstract class. Rather than using public class example we replace the public with abstract. It also has two abstract methods and a normal method. When a class inherits from this abstract class, the subclass will be expected to complete the abstract methods with their definitions as written, meaning if it takes an input then the subclass’s version will need to take the same number and type of input.

abstract class example{ //abstract class
    abstract int exampleMethod(double requiredInput);
    abstract int NoInputMethod();
    public int regularMethod(){
        return 0;
    }

}


public class inheritor extends example{ //normal class extending an abstract class
    public int exampleMethod(double requiredInput){
        return (int) (requiredInput/2);
    }
    public int NoInputMethod(){
        return 0;
    }
}

Interfaces

Interfaces are quite similar to Abstract classes with a few differences. First and foremost, the definition of an interface is a little different rather than using public/abstract class name interfaces use public interface name. Second, rather than using extends a class using an interface uses the keyword implements. Finally, a class can implement multiple interfaces, rather than just one inheritance. The below is an example of defining an interface.

public interface exampleInterface{
    public static final double pi = 3.14;
    public double circumference();
}
public class exampleClass implements exampleInterface{
    public double circumference(){
        return 2*pi*(6);
    }
}

The interface here provides a sample method required by any implementing class, but it also defines a variable pi. Unlike an abstract class, an interface can declare global static variables that can be implemented without any problem. If you tried to perform this using abstraction, the Java compiler would throw an error and crash. An interface is a powerful tool to use when you want to define a simple outline/blueprint for classes that may share key traits. It allows you to define common methods needed for shared functionality across multiple classes. When a class implements an interface, that class is making a contract with the interface saying that it will write all the provided methods in the interface, within the class itself.

Part 3 Key differences

Now at first glance these both sound quite similar, however there are some key differences between the two which will help clarify their differences. You can only inherit from one class, you can implement any number of interfaces as long as one does not overwrite another’s method. Interfaces allow you to include public static final global variables. Abstract classes allow you to provide default variables needed for the class. An abstract can provide completed methods. An Interface should only provide the outlines for the methods and leave the implementation to the user. You can also use inheritance with interfaces as well. For example if you have a superclass shape, and you implement the comparable interface, then all subclasses of shape will be required to complete the comparable interfaces methods, allowing you to effectively inherit multiple interfaces without the need to include it in each individual subclass.

For the Assignment

You will be completing code for a Shape Abstract Class and 3 subclasses, Triangle, Rectangle, and Circle. Shape defines two int variables: x and y, which represent the coordinates of the center of the shape. Shape also defines 2 abstract methods calculateArea() and calculateCircumference(), both return doubles representing the area and circumference of the shapes respectively. For each shape you will have to create the necessary values need to calculate each of these values and getters and setters for each of the values. You will also need to create constructors for each class, the instructions will be included with each class.

Provided below is a UML diagram that gives a visual representation of this lab.

Part 1 Shape: calculateArea() and calculateCircumference()

In the Shape Class you will be writing two abstract methods calculateArea() and calculateCircumference(). Both of these methods will take no parameters and will return a double. Since these methods are abstract, the other classes will define these methods for there specific class.

Part 2 Circle Class

For this part you will be writing the Circle class. This class will have a constructor, accessors and mutators and the abstract methods defined for this class.

Circle Class: Constructor, Circle(double radius)

The Circle class constructor will take in a double that represents a radius of a circle. This value should be stored in an instance variable.

Circle Class: Accessors and Mutators, getRadius() setRadius(double radius)

With the radius instance variable made, accessors and mutators should be made for that variable. The accessor will return the value of the radius instance variable. The mutator should take in a double that can change the radius for a given Circle object.

Circle Class: Abstract Methods, calculateArea() and calculateCircumference()

Since this class extends the Shape class, this means that the Circle class has to implement the abstract methods in the Shape class. In this case, those methods are calculateArea() and calculateCircumference(). For each method respectively, return the area and circumference of a circle with the radius for the object.

Testing Circle Class

In the Test Class, you can now test the code written in this class. Make sure to see if the accessors and mutators are returning correctly. Also, make sure the area and circumference are being returned correctly. For area and circumference, you may assume the results will have 2 decimal points of precision.

Part 2 Rectangle Class

For this part you will be writing the Rectangle class. This class, like the previous, will have a constructor, accessors and mutators and abstract methods defined for this class.

Rectangle Class: Constructor, Rectangle(double height, double width)

The Rectangle class constructor will take in two doubles, one for height and the other for width. These values should be stored in instance variables.

Rectangle Class: Accessors and Mutators, getHeight() getWidth() setHeight(double height) setWidth(double width)

With the instance variables for both height and width made, accessors and mutators for each of the variables should be made. For the accessors, the method should return the value for the appropriate instance variable. For mutators, each mutator will take in a double to change the instance variables. This means there is one accessor and mutator for each instance variable.

Rectangle Class: Abstract Methods, calculateArea() and calculateCircumference()

Like in the Circle class, the Rectangle class also extends the Shape class meaning the abstract methods in the Shape class must be defined in the Rectangle class. Again, these methods are calculateArea() and calculateCircumference(). It may be obvious to you that rectangles do not have circumferences but perimeters. For the calculateCircumference() method, return the perimeter of a given rectangle object. Also, return the area of a given rectangle in the calculateArea() method.

Testing Rectangle Class

In the Test Class, you can now test the code written in this class. Make sure to see if the accessors and mutators are returning correctly. Also, make sure the area and circumference are being returned correctly. For area and circumference, you may assume the results will have 2 decimal points of precision.

Part 3 Triangle Class

For this part you will be writing the Triangle class. As in the previous class, the Triangle Class has a constructor, accessors and mutators and abstract methods defined.

Triangle Class: Constructor, Triangle(double height, double base)

The constructor for the Triangle Class will take two doubles, one for base and one for height. These values should be stored in instance variables.

Triangle Class: Accessors and Mutators, getHeight() getBase() setHeight(double height) setBase(double base)

Like in the Rectangle class, there are now two instance variables, one for height and another for base. Both of these instance variables need to have accessors and mutators. The accessors should return the respective value of an instance variable. The mutators will take a double to change a respective instance variable.

Triangle Class: Abstract Methods, calculateArea() and calculateCircumference()

As seen previously in all the other subclasses, the Triangle class also extends the Shape class. This means that the abstract methods in the Shape class have to be defined in the Triangle class. These methods are calculateArea() and calculateCircumference(). For calculateArea(), return the area of a triangle, which as a reminder is (base*height)/2. As before with the Rectangle Class, there is not a circumference for a triangle. Therefore, for this method return the perimeter of a triangle. As you have the base, and height of the triangle - you can use the pythagorean theorem to figure out the third side, and thus the perimeter. As a reminder, the Pythagorean Theorem is a^2 * b^2 = C^2, which makes the third side the square root of a^2 and b^2. A useful method Math.hypot.

Testing Triangle Class

In the Test Class, you can now test the code written in this class. Make sure to see if the accessors and mutators are returning correctly. Also, make sure the area and circumference are being returned correctly.

Computer Science Department

279 Computer Science Building
1100 Centre Avenue
Fort Collins, CO 80523
Phone: (970) 491-5792
Fax: (970) 491-2466

CS 163/4: Java Programming (CS 1)

Computer Programming in Java: Topics include variables, assignment, expressions, operators, booleans, conditionals, characters and strings, control loops, arrays, objects and classes, file input/output, interfaces, recursion, inheritance, and sorting.