Abstract classes allow us to further extend inheritance in objects. Suppose we have a system that is tracking employees, and we want to implement a function to calculate the pay of our employees. We have a base class, Employee, which implements the name, employee ID, and age of the employee. We want to create a derived class for SalariedEmployee and HourlyEmployee, which can be extended to have functions to calculate the pay of the employee. One further problem is that the pay of our salaried and hourly employees varies by region. Due to this, we want to allow each region's programmers to implement their own pay functions while keeping the base structure of the SalariedEmployee and HourlyEmployee classes.
This sort of situation is one where abstract classes might be valuable. An abstract class allows us to define functions that should exist, without an actual implementation of the function itself. Doing this forces programmers using the class to implement the required functions, but doesn't provide any default functionality. In the case of calculating pay, we want each programmer extending our classes to implement their own pay functions. However, there is some danger in having a default pay function, since it can lead to incorrect numbers if the programmer doesn't extend the function.
We do this by creating an abstract method within our class. An abstract method is one that must be implemented but doesn't have a default implementation. We additionally need to define our class as abstract to tell the compiler that it will contain abstract methods. For example, our Employee base class can be modified to have an abstract method getPay.
Abstract methods are defined almost like properties, they are a single line that defines the return type, as well as the name of the class. When we derive a class from the Employee base class, we must include an implementation of the abstract class getPay.
If we don't implement getPay, we will get an error in the code, so in order to run our code with the SalariedEmployee object, we must implement the abstract method. The main benefit of abstract classes is they allow every object derived from our base object to be more predictable. If I receive code that uses the SalariedWorker object, I am guaranteed that there will exist a function getPay, which returns a double. It allows us to avoid situations where programmers may use unexpected method names or return types, which cause issues in applying the code in the way we need to.