There have been several discussions for this question. But I am looking for a good satisfactory answer that in terms of below oops concepts. a. code reuse b. loose coupling c. polymorphism If any one can explain(with some examples that make use of above specified techniques) when interface is to used and when abstract class is to be used
-
An "interface", in the Java sense, strongly resembles an "abstract class". The difference is that a class can inherit multiple interfaces (plus, at most, one class, abstract or not). Since Java does not allow multiple inheritance of classes, the "interface" gets around that limitation. Other languages (such as C++) have multiple inheritance of classes and hence do not need a separate "interface" concept. – Hot Licks Oct 04 '14 at 20:54
1 Answers
Loose coupling means encapsulated components know just enough about each other to get the job done - nothing more, nothing less. It is a good property for a system to have because loosely coupled components can change its implementation with little to no impact to other dependent components of the system. This increases the maintainability of the system.
Let's use an Iterator as an example. An Iterator is an object that allows one to traverse a container, element by element. There may be many implementations of an Iterator:
- List Iterator
- Vector Iterator
- Stack Iterator
- Linked List Iterator
- Queue Iterator
All implementations vary with respect to the container that they operate on. But the concept of an iterator remains the same - its a way to traverse a container, element by element, without having to know the details of the container implementation. You can say that an Iterator interface is an abstraction for traversing a container.
It is loosely coupled because the details of the container implementation are irrelevant to how the elements are traversed. The clients that use the Iterator do not have to know anything about how the Container is implemented, and vice-versa.
Here is an example of an Iterator interface:
public interface Iterator {
public bool HasNext { get; set;}
public object Next();
}
You could then develop algorithms that are dependent on the Iterator abstraction. For example, you could implement a Reverse algorithm, that traverses a container and reverses the sequence:
public IList<int> Reverse(Iterator iter) {
var list = new List<int>();
while (iter.HasNext) {
list.Insert(0, iter.Next());
}
return list;
}
This implementation of the Reverse algorithm has no idea about what container Iterator is based on (it doesn't care). It could be a StackIterator, VectorIterator, etc.
You could further refactor the implementation by returning an Iterator instead of an IList:
public Iterator Reverse(Iterator iter) {
var list = new List<int>();
while (iter.HasNext) {
list.Insert(0, iter.Next());
}
return new ListIterator(list);
}
Then callers of the algorithm do not have to be dependent on the IList interface - again, looser coupling is the goal here.
Interface vs Abstract Class vs Concrete Class
This is a spectrum of more abstract to less abstract, or in other words, looser coupling to tighter coupling.
Using the example above for an Iterator abstraction, we would have the following spectrum:
Iterator <--> BaseIterator <--> VectorIterator
Iterator is an interface - its the most abstract and exposes the least implementation details, therefore it is least coupled to classes that use it
Base Iterator is an abstract class - it has a partial implementation, and implementing classes will provide the rest of the implementation, classes that use it are dependent on the abstract class (or partial implementation).
VectorIterator is a concrete class - it has a full implementation. Classes that use it are dependent on the concrete implementation, therefore there is tighter coupling to the classes that use it.
Real World Analogy
Here is an analogy. Suppose you're an Employee and about to ask your Employer for a raise. This isn't the first time that any Employee has asked for a raise from his/her manager - its been done many times before by countless others. Suppose there is a general strategy for asking for a raise (without begging) that maximizes your chance of success. Well if you knew that strategy then you could apply it to any Manager with reasonable success throughout your entire career. This is an example of a loosely coupled design. An Employee (any Employee) interacting with a Manager (any Manager) for the purpose of asking for a raise. You could swap out Manager A with Manager B, and your chances for success would still be above average.
Now consider, instead of knowing a general strategy, the employee happens to know of a specific strategy that will work on your current boss (Mr. John A. Smith) because of rumors that he's heard that will make him more agreeable. This is an example of a tightly coupled design. An Employee (Mr. Jones) interacting with a specific Manager (Mr. Smith) for the purpose of asking for a raise. You couldn't swap out Manager A with Manager B, and expect your chance of success to be the same because your strategy will likely only work with Mr. Smith.
In terms of re-usability, the first strategy is more re-usable than the second strategy. Any idea why?

- 52,003
- 16
- 103
- 135
-
-
Interfaces, Abstract Classes, Concrete Classes are all coding constructs. You can talk about abstraction, and loose coupling without talking about code specifically. – Michael Kang Oct 04 '14 at 06:44