There’s an interesting discussion going on in the comments of Eric Wise’s blog about interface implementations versus type inheritance. I respectfully disagree with rlewallen’s post that an interface implementation serves as a "has a" relationship -- and most OO literature would disagree with that notion as well. "Has a" implies a composite relationship where a whole is made up of parts -- An Order object "has a" OrderDetails object. An Invoice object "has a" Customer object. That an interface "has" properties and methods" isn't the same thing, as any type "has" members -- class, interface, struct, and so on.
An interface defines an "is a" relationship... SqlConnection "is a" disposable object (e.g. implements IDisposable). A collection "is a" enumerable object (e.g. implements IEnumerable). Your Customer "is a" comparable object if it implements IComparable.
In terms of when to use one or the other, there are a couple of thoughts that come to mind for me.
First… My feeling is that inheritance is widely overused and that it
often paints developers into a corner. Deep hierarchies tend to
propagate themselves in that specialization rules out wide reuse… so
when the developer needs something that’s “close to, but not quite”
an existing class, they’re typically going to have to subclass again.
This isn’t a .NET specific thing at all, as I saw it a lot in my Java
days and in other OO languages (Delphi, VFP, and even PHP where OO
isn’t enforced). Note that I’ve worked with C++ as well, but am not a
fan of multiple inheritance environments. In general, I think
developers are better served with composite (“has a”) relationships over inheritance. Make small building blocks and then “compose” them to get big components.
The key question is “when do I use an interface versus a implement base class?”.
Years ago, someone (and I’ve long since forgotten who the author was)
explained somewhere that an interface makes sense when a type “is also something else”. That is, a type that implements IComparable
might also be a Customer, a string, an Invoice, and so on — but the
manner of comparing them is very different. So while I know I want to
compare two Customer types or two Invoice types, I really don’t want to
assume anything about how they’re compared.
A type that implements IDisposable
might be a SQL connection, a file handle, a graphics object, and so on.
If all of these things had to inherit from either a “disposable”
implementation, you’d have some unwieldy class hierarchies — and ugly
code as the implementation for disposing of these things is very
different. So if there’s no shared functionality (which would imply
using a base class that provides it), then an interface lets you talk
to widely different objects using the interface contract. The example I
often use is:
A Car, Truck, and Boat might all be subclasses of the
MotorizedVehicle base class. You have shared implementations here,
dealing with starting an engine, basic navigation, and other functions
related to a mototized vehicle. However, the MotorizedVehicle base
class might implement the IDriveable interface – providing Steer,
Accelerate, Decelerate, etc. While you could avoid the
interface and declare those members on the base class, using
IDriveable lets you implement behavior for your Bicycle, Scooter, and
other non-motorized types that can be driven.
