I have read several articles about the differences between an Abstract Class and an Interface.
But it seems, all the articles explain some technical level differences.
Nothing explains the design/architecture level differences. i.e., Which to
choose in a given scenario? either an abstract Class or an Interface.
I did a small research on this. I like to share it with others and also
I want others to check the correctness of these findings.
1. We use interfaces to work around the IS-A relationship that ties
a subclass to a superclass. It is obvious that we don't need IS-A
relationship all the time, but might want to take advantage of polymorphism.
2. We use interfaces to describe behaviors that are unspecific to any kind of objects,
but common to several kind to objects.
A Java class can extend only one class (Java doesn't support multiple inheritance), but it can implement multiple interfaces.
Multiple inheritance has a number of issues such as the diamond problem. In C++, this was solved by making it more complicated (by adding virtual inheritance to the language), in Java it was solved by simply leaving multiple inheritance out of the language.
To make up for the lack of multiple inheritance, Java has interfaces. Interfaces don't have the diamond problem because they don't contain any concrete methods or member variables.
With regard to your points:
1. There is still an IS-A relationship between an interface and the class that implements the interface. I'm not sure what you mean by "it is obvious that we don't need IS-A relationship all the time". Inheritance, whether it's inheriting from a class or from an interface, always implies an IS-A relationship.
2. That's what interfaces are used for most of the time.
like to add one point, interfaces are used to add optional behaviour in class. Consider Comparable interface that allows a class to make sure that its instances are ordered with respect to other mutually comparable objects. Such interface is called a Mixin. You cannot define Abstract Classes as mixin.
Looking at it from a practical point of view I would answer with "loosely coupled code"
A class that implements an interface can be changed with any other class that uses the same interface. One immediate benefit is testing.
If I create a SaleDao interface rather than abstract class I can easily change dao implementations. If SaleDao were an abstract class or descendant from an abstract class I can't easily change the actual used class to something else for testing purposes.
Say I have interface BaseDao (which contains all my basic hibernate stuff) and SaleDaoImpl extends BaseDao and implements SaleDao. Then:
I can then have interface TestDao (which is used for testing purposes) and SaleDaoTest extends TestDao and implements SaleDao. Then:
Since I use Spring I don't actually write the above mentioned code. I fetch it from the application context which is built from an xml file. It is a trivial thing to change the application context xml file for testing purposes and then back for production.
It becomes more like:
and the xml
This is a trivial example, but if you imagine working on more complex code like an applications flow or some algorithm to calculate things. Then version A of the system and version B of the system will be interchangeable as long as they implement the same interface. If you wired everything through the xml configuration then all you need to do is change a few lines and you're done.