Interfaces Vs Abstract class - Real World

Interfaces Vs Abstract class - Real World


I still see people get confused about interfaces and abstract class, this is mostly because we are looking these aspects from Java Perspective. Since these concepts are coming from Object Oriented Principles, better to check the definitions from OOAD or UML. These concepts are not just available in Java, they are in other languages with different names.

Here we are talking about totally different two concepts. One on the base of Generalization (inheritance) and another based on Realization (implementation or interfaces).

Interfaces (Realization)

Let me first explain what is an interface and when can you need to use it,
Interfaces are just literally contracts (a written or spoken agreement),
Realization - you realize or be aware

con·tract
noun
plural noun: contracts
ˈkäntrakt/
  1. 1.
    a written or spoken agreement, especially one concerning employment, sales, or tenancy, that is intended to be enforceable by law.
    "both parties must sign employment contracts"
    synonyms:agreementcommitmentarrangementsettlementunderstandingcompactcovenantbondMore

re·al·i·za·tion
ˌrē(ə)ləˈzāSH(ə)n/
noun
  1. 1.
    an act of becoming fully aware of something as a fact.
    "there was a growing realization of the need to create common economic structures"
    synonyms:awarenessunderstandingcomprehensionconsciousnessappreciationrecognitiondiscernmentMore
For any contract, there are two parties,
1. Person who design/create the contract
2. The person who agree/oblige to follow the contract.

For example, if you are hired as a developer in a company you sign a contract with that company. Which means you can (realize what can be done) do only what is mentioned in the contract (other words you are obliged to the contract). This contract is defined by the company. Here it doesn't matter whether the developer is a Java or C++ developer. Every developer has to obey the contract.

Note: The developer can also be a trainer in some case (in the real world) if he agrees with Trainer Contract, this is achieved when a person signs multiple contracts.

When it comes to programming (esp in Contract based Programming Paradigm), as a designer of a component you write a contract.
Example, If you are designing an API for Employee manipulations, you define a contract with all the required methods. Since this is just a contract, you do not write any implementation. (Say, your company has a contract that says all developer has to check-in all their code to the git repo before end-of each day. The contract does not tell how to check-in or what tools to use (implementation). The developer has the freedom to use CLI or GitHub or Eclipse etc...)

Your contract will look like,

Employee Contract  {
     You should allow users to create a new employee,
     You should allow users to update an existing employee
}

Note: As a designer, you decided not to delete your employee via API. (I have shown here just to explain contracts are not same across API's or Applications, this is how you designed your application).

Like developers in our example, let us assume we have 4 components who would like to be an Employee Manipulators. Let us name them as
1. Java API Employee's - who expose employee as Java API interfaces
2. Rest API Employee - who expose employee as Rest interfaces
3. SOAP API Employee - who expose employee as SOAP interfaces
4. Employee Contract Verifier - some class who invokes Employee API for testing the contract or functionalities.

Regardless of the component types, everyone has to oblige the contract, means each of these components should have the option to create and update employee. For this reason, they sign the contract (in Java you use 'implements' and '@Override', so that the compiler can alert you if you are deviating from the contract. I don't know why we need @Override for Java methods for interfaces implementation. You are not overriding anything here. In C# you use just a colon (:))

The above components will be like this,

JavaAPIComponent oblige EmployeeContract {
   create, update //these implementations will directly call the DB to do operations
}

RestAPIComponent oblige EmployeeContract {
   @ExposeAsHttpRestPost create,
   @ExposeAsHttpRestPost update
   //these implementations will directly call the DB or JavaAPI to do operations
}

SOAPAPIComponent oblige EmployeeContract {
   @ExposeAsHttpSoapPost create,
   @ExposeAsHttpSoapPost update
   //these implementations will directly call the DB or JavaAPI to do operations
}


TestEmployeeAPIComponent oblige EmployeeContract {
   create, update //these implementations will directly call the SOAP or REST interfaces to test the operations.
}

Key points to be noted here is,
1. No implementation in Contract - because you tell WHAT to do and not HOW to do
2. Users of the implementation class can 100% trust on the class as they oblige with the contract (like your manager trust you as a developer)
3. Variations of implementation can be there, but they can't change the contract for any reason.

Abstract Class (Generalization)

An abstract class is a class (blueprint) which gives partial implementation and let others complete the implementation via extending the class. This is mostly done because, during the design of the class, the designer does not know how a particular method can be handled (implemented).

For example,  In your application, you need to convert a CSV file to various formats (Ex, JSON, and XML). One easy way of doing is you can design specific classes for formattings like CSV2JsonConverter and CSV2XMLConverter. In this case, you have to write the CSV reading part multiple times, which is not good. Also during your initial design phase, you may not know what type of converters your application supports.

Now let us see how this can be designed.

abstract CSVConvertor {
       public  convert(file);
       protected abstract format(line);
}

The beauty of this design is, the class says CSVConvertor it has a convert method to convert CSV file to X format. (because at the time of design we do not know what is X).

In this design, the conversion is implemented within "convert" method, but it is partial, because we don't know how to format. In such cases we just abstract them saying, we do format by invoking "format" method. (this is why we put 'abstract' keyword in front of the method).

This looks good from the design perspective, but in runtime, this creates an issue, because the Runtime doesn't know how to invoke format, as it does not have implementation reference.  Before looking into how can we solve this, let us think why the class has to be 'abstract'. This is not just because Java documentation says, if you have at least one 'abstract' method the class has to be abstract.

Ask yourself about what will happen if we create an instance of CSVConvertor and call the 'convert' method? Of course, it will fail - because the implementation of the 'format' method is still unknown.
Now you have to restrict users from creating an instance of this class. (Yes you can still create a private constructor :))

More than that how do you tell users that, someone has to provide an implementation for 'format' method?

This is when you use 'abstract' keyword for the class, which helps users to know they have to provide an implementation for 'abstract' methods. The compiler also restricts other from creating the instance.
By making the class abstract, you tell others, this class is just an abstraction and for using it we need another concrete class which extends this.

Now let us see how can we provide an implementation for 'format' method?

The only way is to use Generalization or Extends. You extend the class and override the abstract method.

For Example,
class JSONConvertor extends CSVConvertor {
       format(line) {
              format to json
       }
}


Now the users can use this as,

CSVConvertor csvConvertor = new JSONConvertor();
String json = csvConvertor.convert(csvfile);


Hope this is clear for everyone. In general, interfaces and abstract are used to convey two different principles, it gets confused because the way Java is implemented.

I prefer always learn the Object Oriented Principles without any languages. Later you apply these principles to the features supported in the language.