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.
}
}