Implementing public interfaces in protected "mode"

Note: this entry has moved.

Quite often, we create interfaces as a way to allow extensibility in our OO projects. But as you know, all the members of the interface are public. So, if we don't want to polute our objects public members with the implementation of an interface that was intended for extenders and not the regular user, we can simply make the interface implementation explicit, effectively hiding the member from the class public interface:

public interface IExtensible
{
  void Extend( object other );
}		

public Customer : IExtensible
{
  void IExtensible.Extend( object other )
  {
    // Do something really cool.
  }
}

So far so good. Now the Extend method will no longer appear in intellisense nor will it be available directly. To use it, it has to be casted to the IExtensible interface, but that isn't a problem at all, since most probably, the feature is intended to be used by a method that receives a parameter of type IExtensible anyways.
But now the interface implementation can't be extended by inheritors of Customer! A pattern I've seen quite often throughout the .NET Framework to solve this is doing a double implementation of the method, one private (the explicit interface implementation) and another protected and virtual, so that inheritors can effectively override the base class' private interface implementation behavior:

public class Customer : IExtensible
{
  protected virtual void Extend( object other )
  {
    // Do something really cool, but let inheritors change that.
  }

  void IExtensible.Extend( object other )
  {
    // Passthrough to the "real" implementation.
    Extend( other );
  }
}

What we got now, is a non-poluted public interface for our class, yet inheritors have full access to features that were intended for their use, such as our interface that allows extensibility. If they don't want to inherit our implementations, they can always implement the interface directly, of course:

public class ExtendedCustomer : Customer
{
  protected override void Extend( object other )
  {
    // Stop doing cool things and just do the work.
  }
}

4 Comments

  • I strongly recommend against using reflection in production code that needs to be performant. It's extremely slow, and the solution proposed can have a serious impact in the overall performance, specially if the method is called frequently.

  • Very true, but in the case of say built-in ASP.NET Controls (as Andy was talking about) that seems to be the only way. Of course, unless one just reimplements the whole logic.

  • Well, that may change with the pattern I showed in future versions of ASP.NET... who knows ;)

  • Yes, my technique was designed solely as a work around for when the original implementor only implements explicitly/privately. Never do the reflection hack unless you have to.

Comments have been disabled for this content.