Name Hiding with Interfaces
The most common way to call a method implemented from an interface is to cast an instance of that class to the interface type and then call the desired method. While this is valid and many people (including myself) use this technique, technically you don't have to cast the object to its implemented interface to call that interface's methods. This is because when a class implements an interface's methods, those methods are also public methods of the class. Take a look at this C# code and especially the Main method to see what I mean: -
using System; public interface IDataBound { void Bind(); } public class EditBox : IDataBound { // IDataBound implementation. public void Bind() { Console.WriteLine("Binding to data store..."); } } class NameHiding1App { // Main entry point. public static void Main() { Console.WriteLine(); EditBox edit = new EditBox(); Console.WriteLine("Calling EditBox.Bind()..."); edit.Bind(); Console.WriteLine(); IDataBound bound = (IDataBound)edit; Console.WriteLine("Calling (IDataBound)EditBox.Bind()..."); bound.Bind(); } }
This example will now output the following: -
Calling EditBox.Bind()... Binding to data store... Calling (IDataBound))EditBox.Bind()... Binding to data store...
Notice that although this application calls the implemented Bind method in two different ways-one with a cast and one without-both calls function correctly in that the Bind method is processed. Although at first blush the ability to directly call the implemented method without casting the object to an interface might seem like a good thing, at times this is less than desirable. The most obvious reason is that the implementation of several interfaces-each of which might contain numerous members-could quickly pollute your class's public namespace with members that have no meaning outside the scope of the implementing class. You can prevent the implemented members of interfaces from becoming public members of the class by using a technique called name hiding.
Name hidingat its simplest is the ability to hide an inherited member name from any code outside the derived or implementing class (commonly referred to as the outside world). Let's say that we have the same example as we used earlier where an EditBox class needs to implement the IDataBound interface-however, this time the EditBox class doesn't want to expose the IDataBound methods to the outside world. Rather, it needs this interface for its own purposes, or perhaps the programmer simply doesn't want to clutter the class's namespace with a large number of methods that a typical client won't use. To hide an implemented interface member, you need only remove the member's public access modifier and qualify the member name with the interface name, as shown here: -
using System; public interface IDataBound { void Bind(); } public class EditBox : IDataBound { // IDataBound implementation. void IDataBound.Bind() { Console.WriteLine("Binding to data store..."); } } class NameHiding2App { public static void Main() { Console.WriteLine(); EditBox edit = new EditBox(); Console.WriteLine("Calling EditBox.Bind()..."); // ERROR: This line won't compile because // the Bind method no longer exists in the // EditBox class's namespace. edit.Bind(); Console.WriteLine(); IDataBound bound = (IDataBound)edit; Console.WriteLine("Calling (IDataBound)EditBox.Bind()..."); // This is OK because the object was cast to // IDataBound first. bound.Bind(); } }
The preceding code will not compile because the member name Bind is no longer a part of the EditBox class. Therefore, this technique enables you to remove the member from the class's namespace while still allowing explicit access by using a cast operation.
One point I want to reiterate is that when you are hiding a member, you cannot use an access modifier. You'll receive a compile-time error if you try to use an access modifier on an implemented interface member. You might find this odd, but consider that the entire reason for hiding something is to prevent it from being visible outside the current class. Since access modifiers exist only to define the level of visibility outside the base class, you can see that they don't make sense when you use name hiding.