When should I choose to design using interfaces and when should I choose to use Abstract Classes?
Interfaces’ purpose in life is much more clear than abstract classes: they’re meant to define a “contract” between a client and a server. They prescribe a precice way that two components communicate with one another. They provide a means of component interchangeability.
Abstract Classes provide the same benefits of “interchangeability” and polymorphism. However, Abstract Classes have a few limitations. Here’s an overview of the differences and the implications:
Classes may only inherit from one Abstract Class, whereas classes may inherit from multiple interfaces
The implication of this fact helps us understand the real measning behind interfaces. Interfaces define a “prescribed capability” wheras abstract classes define a “design contract”.
This quality of “prescribed capability” is apparent in most well written component oriented code, and is illustrated by the fact that most interface names are adjectives related to a verb. For example, some common .net interfaces are:
· IComparable
· ISerializable
· IEquatable
· IFormattable
The “…able” suffix affirms this concept even more. Interfaces describe an object’s “capabilities”. Interfaces are used when one component attempts to determine whether or not another component supports a certain capability. If it does, then the component can be used. The details of how the actual object behind the interface implements the prescribed capabilities is of no concern to the client.
So it makes sense that a class would be able to inherit multiple interfaces – a component based framework allows any given component to fulfill more than one capability.
Further more, using the concept of prescribed capabilities (i.e. adverbs) to design class interfaces leads to much more robust and elegent software designs. The book “Head First Design Patterns” provides good insight into this concept in its introduction in which they recommend thinking of interfaces interms of “behaviors a class may support” rather than “a generic type of class”.
So interfaces really should be used to describe behavior capability.
Designing around behavior capability is less intuitive and designing around types.
Wheras interfaces are tailord to describing behaviors, abstract classes are more tailored to describing types.
We said before that “designing against capabilities rather than types” leads to more elegent designs. While this is true in terms of the overall structure of a software system, it does not mean that there are not benefits to designing against types.
Abstract Classes allow a way of providing a “design contract” rather than a “behavior contract”. A design contract helps a designer understand how a derived class should “look” rather than “behaive”. A design contract influences the backend design of a system rather than the front end. It provides a way of enforsing certain design rules when designing derived classes or creating implementations of interfaces.
[There are two issues: 1) Enforcing a common external design – enforcing how a component should be used, 2) Enforcing a common internal design – enforcing how various implementations of an interface are built. Theres a lot more here!]
Another benefit of Abstract Classes is that they are actual classes, which in .net means that they’re System.Objects. System.Objects have a lot of benefits:
- Type conversion
- Serialization (I think…)
- Others?
A General Purpose Template
So which do we use? Use both!
Interface ILoadable, IPlayable
^
Abstract Class Bscan
^
Concrete Classes M9Bscan, CorelisBscan
In conclusion, although interfaces and abastract classes are very similar from semantic and binary perspectives, they have quite different purposes and in terms of design should be used differently.
Guidelines
- Abstract Classes should be as abstract as possible; i.e. they should look as much like interfaces as possible
- “default behavior” should be used with care
- Class Properties should not be interfaces