In the implementation shown so far, the class that
implements the interface (Document
)
creates a member method with the same signature and return type as the
method detailed in the interface. It is not necessary to explicitly
state that Document
is implementing
IStorable
, for example; the compiler
understand this implicitly.
What happens, however, if the class implements two interfaces,
each of which has a method with the same signature? This might happen if
the class implements interfaces defined by two different organizations
or even two different programmers. The next example creates two
interfaces: IStorable
and ITalk
. ITalk
implements a Read( )
method that reads a book aloud.
Unfortunately, this conflicts with the Read( )
method in IStorable
.
Because both IStorable
and
ITalk
have a Read( )
method, the implementing Document
class must use
explicit implementation for at least one of the
methods. With explicit implementation, the implementing class (Document
) explicitly identifies the interface
for the method:
voidITalk
.Read( )
Marking the Read( )
method as a
member of the ITalk
interface
resolves the conflict between the identical Read( )
methods. There are some additional
aspects you should keep in mind.
First, the explicit implementation method cannot have an access modifier:
void ITalk.Read( )
This method is implicitly public. In fact, a method declared
through explicit implementation cannot be declared with the abstract
, virtual
, override
, or new
keywords.
Most importantly, you cannot access the explicitly implemented method through the object itself. When you write:
theDoc.Read( );
the compiler assumes you mean the implicitly implemented interface
for IStorable
. The only way to access
an explicitly implemented interface is through a cast to the
interface:
ITalk itDoc = theDoc as ITalk; if (itDoc != null) { itDoc.Read( ); }
Explicit implementation is demonstrated in Example 13-6. Note that there
is no need to use explicit implementation with the other method of
ITalk
:
public void Talk( )
Because there is no conflict, this can be declared as usual.
Example 13-6. Explicit implementation
using System; namespace OverridingInterfaces { interface IStorable { void Read( ); void Write( ); } interface ITalk { void Talk( ); void Read( ); } // Modify Document to also implement ITalk public class Document : IStorable, ITalk { // the document constructor public Document( string s ) { Console.WriteLine( "Creating document with: {0}", s ); } // Implicit implementation public virtual void Read( ) { Console.WriteLine( "Document Read Method for IStorable" ); } public void Write( ) { Console.WriteLine( "Document Write Method for IStorable" ); } // Explicit implementation void ITalk.Read( ) { Console.WriteLine( "Implementing ITalk.Read" ); } public void Talk( ) { Console.WriteLine( "Implementing ITalk.Talk" ); } } class Tester { public void Run( ) { // Create a Document object Document theDoc = new Document( "Test Document" ); IStorable isDoc = theDoc as IStorable; if ( isDoc != null ) { isDoc.Read( ); } // Cast to an ITalk interface ITalk itDoc = theDoc as ITalk; if ( itDoc != null ) { itDoc.Read( ); } theDoc.Read( ); theDoc.Talk( ); } [STAThread] static void Main( ) { Tester t = new Tester( ); t.Run( ); } } }
The output looks like this:
Creating document with: Test Document Document Read Method for IStorable Implementing ITalk.Read Document Read Method for IStorable Implementing ITalk.Talk