OCA Java SE 8 Class Design - Java Abstract Classes








An abstract class is a class that is marked with the abstract keyword and cannot be instantiated.

An abstract method is a method marked with the abstract keyword defined in an abstract class.

An abstract method has no implementation in the class in which it is declared.

The following code is based on our Shape and Rectangle description:

public abstract class Shape { 
  protected int edge; 
  public void eat() {  
    System.out.println("Shape is eating"); 
  } 
  public abstract String getName(); 
} 

public class Rectangle extends Shape { 
  public String getName() { 
    return "Rectangle"; 
  } 
} 

Shape class is declared abstract and Rectangle is not.

The member edge and the method eat() are marked as protected and public, respectively; therefore, they are inherited in subclasses such as Rectangle.

The abstract method getName() is terminated with a semicolon and doesn't provide a body in the parent class Shape.

This method is implemented with the same name and signature as the parent method in the Rectangle class.





Defining an Abstract Class

An abstract class is not required to include any abstract methods.

For example, the following code compiles without issue even though it doesn't define any abstract methods:

public abstract class Shape { 
} 

Although an abstract class doesn't have to implement any abstract methods, an abstract method may only be defined in an abstract class.

For example, the following code won't compile because an abstract method is not defined within an abstract class:

public class Shape { 
  public abstract void calculate();  // DOES NOT COMPILE 
} 

For example, neither method in the following code will compile because the methods are marked as abstract:

public abstract class Main { 
  public abstract void s() {}  // DOES NOT COMPILE 
  public abstract int g() {  // DOES NOT COMPILE 
    return 10; 
  } 
} 

s() doesn't compile because two brackets are provided instead of a semicolon.

g() doesn't compile because it also provides a body to an abstract method.





Default Method Implementations in Abstract Classes

You can't provide a default implementation to an abstract method in an abstract class.

You can define a method with a body-you just can't mark it as abstract in an abstract class.

As long as you do not mark it as final, the subclass still has the option to override it.

An abstract class cannot be marked as final.

An abstract class is one that must be extended by another class to be instantiated, whereas a final class can't be extended by another class.

For example, the following code snippet will not compile:

public final abstract class Shape {  // DOES NOT COMPILE 
} 

An abstract method may not be marked as final for the same reason that an abstract class may not be marked as final.

Once marked as final, the method can never be overridden in a subclass and it is impossible to create a concrete instance of the abstract class.

public abstract class Shape { 
  public abstract final void aMethod();  // DOES NOT COMPILE 
} 

Example 2

A method may not be marked as both abstract and private. The compiler will complain if you try to do the following:

public abstract class Shape { 
  private abstract void print();  // DOES NOT COMPILE 
} 

public class Rectangle extends Shape { 
  private void print() { 
    System.out.println("rectangle is printing"); 
  } 
} 

The abstract method print() defined in the parent class Shape is not visible to the subclass Rectangle.

Even though Rectangle does provide an implementation, it is not considered an override of the abstract method since the abstract method is unreachable.

The compiler throws an exception as soon as private and abstract are applied to the same method.

Example 3

The following code changed the access modified from private to protected in the parent class Shape, would the code compile?

public abstract class Shape { 
  protected abstract void print(); 
} 

public class Rectangle extends Shape { 
  private void print() {  // DOES NOT COMPILE 
    System.out.println("Humpback whale is printing"); 
  } 
} 

The code above will still not compile.

For overriding a method, the subclass cannot reduce the visibility of the parent method, print().

Because the method is declared protected in the parent class, it must be marked as protected or public in the child class.