Interfaces vs. Abstract Base Classes
This is something I’ve gone back and forth on for a while now. Having faced this decision once again in my latest project, I figured it was time to solidify my thoughts on it. Here’s my take on the seemingly endless Interface vs. Abstract Base Class debate.
As we know, a well-structured application favors loose coupling to reduce dependency among classes and to make the resulting system less rigid, and more resilient to change. One of the ways we do that, as originally proposed by the GoF, is this:
Program to an interface, not an implementation.
Here, they are speaking of an “interface” in a general sense; that is, a construct that provides a specification for a type without implementing its members. When a class implements the interface, it is forced to implement each of the members defined in it. This serves as a “contract” to whatever object consumes an instance of the implementing class -- in effect, it warrantees that the members defined by the interface will be available.
Therefore, if a member in class A consumes an instance of class B, where B is an implementation of interface N, you can rewrite A to consume N instead. A never needs to be aware of B’s actual type, as long as B fulfills the contract defined by N. In fact, A can (and should) remain totally unaware of the existence of B. This lets you alter B’s implementation of N without breaking A, and provide new implementations of N (C, D, E and so on), all of which can be readily consumed by A without alteration. That’s loose coupling in action.
In .NET languages, there are two constructs available for accomplishing this: using an abstract class, or an actual interface construct. Both require the classes that inherit it (in the case of an abstract class) or implement it (in the case of an interface) to provide implementations for any abstract members. Hence the debate: which is better? Are there situations in which it makes sense to opt for one over the other?
I happen to be currently reading Dino Esposito’s latest book, Microsoft .NET: Architecting Applications for the Enterprise, in which he offers the following opinion:
Should you use an interface? Or should you perhaps opt for an abstract base class? In object-oriented languages that do not support multiple inheritance – such as Java, C#, or Visual Basic .NET – an interface is always preferable because it leaves room for another base class of your choice.
As great as this book has been so far (I’m about halfway through), I sort of feel a little uneasy about this “interface is always preferable” argument. While it’s true that an interface may be more flexible in that it allows for the possibility of inheriting from another base class, I think this argument holds a lot less water in the case where the interface is meant to define a type’s core functionality.
In other words: I wonder if it doesn't make more sense, at least from a semantic point of view, to use an abstract base class if the types that will inherit from it share common core functionality. If the types merely share a common ability or characteristic, yet are otherwise functionally unrelated, then use an interface.
Or, to put it in even simpler terms: as a general rule, if it can be said that an object of type B is a kind of A, then class B should inherit from the abstract class A. On the other hand, if A is only a characteristic of or an ability of an object of type B, then class B should implement the interface A.
Let’s take a typical example from the .NET Framework BCL, like SqlConnection.
public sealed class SqlConnection : DbConnection, ICloneable
You see that this class inherits from DbConnection, which is an abstract class. DbConnection defines members which are common to all types of connections. This abstract class is in turn inherited by OdbcConnection, OleDbConnection, and OracleConnection, as well as SqlConnection. These represent specific types of connections, which all share a common functionality in that they are all used to connect to a database.
You’ll also notice that SqlConnection implements the ICloneable interface, because it needs to support cloning beyond that supplied by MemberwiseClone (which all .NET objects already inherit). However, the need for an object to be able to deep-copy itself is not a requirement exclusive to connections. It is, in fact, a necessary feature for many other types, most of which are totally unrelated to connections. For example, System.Xml.XmlNode, System.Array, and System.Web.UI.WebControls.Parameter all require the ability to clone, and thus each of them implements the same ICloneable interface.
You could restate it this way: A SqlConnection object is a kind of DbConnection, and cloning is an ability of a SqlConnection object. (You could also say that clonability is a characteristic of a SqlConnection object.) Therefore, SqlConnection inherits the abstract class DbConnection, and implements the interface ICloneable.
If nothing else, this should indicate to you why it’s no accident so many of the .NET interfaces end with the suffix “-able”.
Now, I realize the distinction I’m drawing here may not be that important in many cases. Of course, the real point is how separating specification from implementation lets us “program to the interface” – that is, to write code that’s designed to work with a base class (or interface, as the case may be), and to be able to use that code with instances of any class derived from the base class. This lets us leverage the benefits of polymorphism to create more robust code.
So anyway, that’s pretty much when I’m standing on the Interface vs. Abstract Base Class issue. At least for the rest of this week. ;-)
Subscribe to this blog for more cool content like this!
You've been kicked (a good thing) - Trackback from DotNetKicks.com
Thank you for submitting this cool story - Trackback from DotNetShoutout
Pingback from Reflective Perspective - Chris Alcock » The Morning Brew #329
9efish.感谢你的文章 - Trackback from 9eFish
Pingback from Yet another debate on Interfaces vs. Abstract Base Classes | Xelluloid
Pingback from Noch eine Debatte ??ber Interfaces vs. Abstrakte Klassen | Xelluloid
My last "versus" post seemed to elicit a good number of interesting responses. Today, I'm musing about Singletons vs. Static Classes -- two constructs which appear to accomplish the same task. Or do they?