Transcripted Summary

The last major principle of object-oriented programming is abstraction, and that will be the focus of this chapter.

Abstraction is defined as something that exists in theory but does not have a concrete existence. In Java, we have the reserved word, abstract — which is a non-access modifier that can be used on classes and methods. It is used when you want to define a template for a class or a method, but do not intend for it to be used as is.

An abstract class is not designed to be instantiated. It's designed to be extended, thus pushing the burden of implementation onto the subclass.

For example, a shape is an abstract concept. It can specify perhaps some general behaviors that a type of shape would have. But it's too abstract of a concept to actually define what that behavior should be.



So, this class cannot be instantiated, but its purpose is to serve as a parent class for more specific subclasses to extend from. An abstract method has no body, only the signature of the method is defined, and it is not designed to be run as is. It's designed to be overridden by a subclass.



In this case, we know that one should be able to calculate the area of a shape. But how that is done depends on the type of shape that it is.

There's no such formula to add to the body of the method in the Shape class, because it literally does not exist. This is meant to be a template to set a standard that any subclass of Shape should provide behavior for this method.

Let's look at this in more detail.

Here we have a Shape class.

Let's say that we wanted to create an abstract method in here.

package chapter11;

public abstract class Shape {

    abstract double calculateArea();
}

We would use the reserved word, abstract, which is a non-access modifier, and then we would give the return type, and the method name, followed by the parameter list that we like to have (in this case, we don't need anything), and then a semicolon.

That's it, no curly braces, no body to this method.

Now because we have an abstract method in this class, we are required to make the class itself abstract as well. We can make a class abstract by simply writing the word abstract before class.

An abstract class doesn't only have to contain abstract methods.

It can contain implemented methods as well. So, let's create a print method.

public void print(){
    System.out.println("I am a shape");
}

So, notice the print method is not abstract and the calculateArea() method is.


Now, let's go to the Rectangle class, and we are going to extend from the Shape class.

public class Rectangle extends Shape(

}

Right away, we get a compilation error, and it's saying that this class must either be declared abstract or implement the abstract method calculateArea().



So, we've inherited an abstract method when we extended Shape — which means we have to provide the implementation for that abstract method.

If, for example, we didn't want to provide the implementation, then we don't have to do it. But this class itself would then need to be declared as abstract because it contains abstract methods. Technically, because they were inherited.

Let's say the Shape had 20 abstract methods here, and Rectangle only wanted to implement 10 of them. Then that would be a case where it could implement those 10, but still, because there is at least 1 abstract method within this class, it would still have to be abstract itself.

Let’s go ahead and implement the abstract methods that Rectangle inherited.

To do so, you need to add those methods that you inherited that were abstract.

An easy way to do that in IntelliJ would be to use the right-click and then the generate option. Then there's this option that says Implement Methods and it'll show you all of the methods that need to be implemented.



public class Rectangle extends Shape {

    @Override
    double calculateArea() {

        return 0;

    }
}

Now of course we'll want to change this return 0; to be something more meaningful.

So, let's go ahead and actually add fields and everything to this Rectangle class.

# Rectangle.java

package chapter11;

public class Rectangle extends Shape {

    private double length;
    private double width;

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    public Rectangle(double length, double width){
        setLength(length);
        setWidth(width);
    }

    @Override
    double calculateArea() {
        return length * width;
    }
}

Now let's go to another class, ShapeTester.

We're going to test out what we made here.

So, let's make a Shape object and call it rectangle. Then we’ll attempt to make it a new instance of Shape.

Notice the compilation error. That's because you cannot instantiate an abstract class.



Again, abstract classes are meant to be a template. They are not meant to be used as is. So, you cannot instantiate it. The error is clear. Shape is abstract, cannot be instantiated.

You can use an abstract class as a type, but just like we saw in the last chapter, you would have to instantiate it with one of its subclasses.

So, we could say Rectangle and let's pass in a length and a width. And then we could just say rectangle.print(), and rectangle.calculateArea().

# ShapeTester.java

package chapter11;

public class ShapeTester {

    public static void main(String[] args){

        Shape rectangle = new Rectangle(5, 7);
        rectangle.print();
        System.out.println(rectangle.calculateArea());
    }
}

Again, even though rectangle is of type Shape, and there is a calculateArea() method in the Shape class, because we overrode it with our instantiation of Rectangle, then that is the one that will be used.

However, the method print is only in the Shape class, and we inherited that. It wasn't abstract, so we can use that.

And when we call calculateArea(), we're going to get a double back. So, let's just go ahead and print it out.

All right let's run this.



Perfect, so, “I am a shape”, which came from the Shape class, and then 35 was the implementation from the Rectangle class.


# Abstraction Key Points

Some key points about abstraction.



  • Abstract classes and methods are templates that are meant to be implemented by their subclasses.

  • The classes and methods are declared abstract by using the abstract keyword.

  • If a subclass inherits from an abstract class, it must implement its abstract methods or the class itself must be declared as abstract.

  • Abstract classes cannot be instantiated. They are only to be used as a superclass. If even one method in a class is abstract, then the entire class must be declared abstract as well.



Resources