Q. Should I choose interfaces or base classes for polymorphism?

Asked by Michael Weinhardt. Answered by the Wonk on December 22, 2002

A.

Michael Weinhardt asked me a darn good question the other day. He wanted to know why some parts of .NET use interfaces and some use base classes for their polymorphic behavior. Both of these styles of architecture can be found in the .NET design-time architecture. The core of the design-time architecture is the IComponent interface from the System.ComponentModel namespace. An implementation of the IComponent interface allows a .NET class to be shown on the Toolbox, dropped onto a design surface and manipulated via the Property Browser. All this is based on the ability to set the Site property from the IComponent interface:

interface System.ComponentModel.IComponent : IDisposable {
  ISite Site { get; set; }
  public event EventHandler Disposed;
}

In this case, VS.NET uses the IComponent interface (and Reflection) to hook any component into its design environment without needing any implementation details. On the other hand, to help VS.NET convert back and forth between strings in the Property Browser and properties of custom types in your components (or controls), a component can expose a custom type converter class using an attribute:

[TypeConverterAttribute(typeof(FractionTypeConverter))]
class Fraction {...};

In this case, VS.NET requires help from the FractionTypeConverter to translate strings of the form "4/5" into instances of the Fraction class:

class FractionTypeConverter : TypeConverter {
  public override object ConvertFrom(...) {
    string from = (string)value;
    int slash = from.IndexOf("/");
    int numerator = int.Parse(from.Substring(0, slash));
    int denominator = int.Parse(from.Substring(slash + 1));
    return new Fraction(numerator, denominator);
  }
  ...
}

Notice that instead of implementing an ITypeConverter interface, the FractionTypeConverter derives from the TypeConverter base class. The TypeConverter class provides a set of virtual methods that any custom type converter can implement or not, depending on its needs. The base class implementations of the virtual methods provide default functionality that will be applicable in a large percentage of cases, making it justified in many cases to rely on the base class implementation.

In the case of components, VS.NET requires the class to implement the IComponent interface and will use the abstract members to hook up with arbitrary components. On the other hand, for type converters, VS.NET requires a derivation from the TypeConverter base class, calling the virtual methods that may or may not be overridden in the derived class. So why the difference?

One major difference between interfaces and base classes is that interfaces require all members to be implemented, while base classes only require abstract members to be implemented, while allowing virtual members to be overridden optionally. In the case of IComponent vs. TypeConverter, IComponent has two members, making it easy to implement. TypeConverter, on the other hand, provides thirty-two, eleven of which are virtual. That's a heck of a lot of functionality to require a type converter to implement, especially if the majority of the implementation is common amongst type converters, making a base class seem like a darn good idea in the case of a type converter.

On the other hand, because .NET only supports a single base class, a custom type converter must derive from only TypeConverter. A type converter can't also be a Control, for example. Interfaces, of course, have no such limitation. A class can implement any number of interfaces.

Where Are We

How do you decide between interfaces and base classes for your polymorphism? I recommend taking some clues from the .NET framework itself. In the case where the set of methods doesn’t expose a large amount of common functionality across many implementations, prefer interfaces. On the other hand, where there is a large amount of common functionality, prefer base classes (all other things being equal). One exception to this rule that you should prefer interfaces for remote objects to completely separate the client and the server from each other.

And, if you want the maximum of flexibility and ease of implementation, you can define an interface, depend on that interface from your clients but also provide a base implementation of that interface. For example, .NET could define the ITypeConverter interface, which VS.NET could depend on, but still provide a TypeConverter base class that custom type converters could derive from to provide ease of implementation, e.g.

// imaginary
interface System.ComponentModel.ITypeConverter {...}
class System.ComponentModel.TypeConverter : ITypeConverter {...}
class MyNamespace.MyCustomTypeConverter : TypeConverter {...}

In fact, .NET does just that for the IComponent interface and the Component base class:

// real
interface System.ComponentModel.IComponent : IDisposable {...}
class System.ComponentModel.Component : System.ComponentModel.IComponent, ... {...}
class MyCustomComponent : Component {...}

Providing both an interface and a base class requires more work, but it does help you to depend less on implementation details when designing a polymorphic architecture, especially for extension by 3rd parties.

How I Figured This Out

The answer to this question is based on years of designing C++ base classes and COM interfaces as well as an understanding of the .NET framework and how Microsoft chose to answer this question. I also ran my ideas past Michael before posting this answer.

How To Avoid This In The Future

I think Michael did the exact right thing when he noticed the difference between interfaces and base classes as used for polymorphism in .NET -- he asked. Design questions like these always have an answer that boils down to "it depends," and the best way to get answers to these kinds of questions is to ask other folks that have thought the same thoughts.

Feedback

I have feedback on this Ask The Wonk answer