Section 8.3. Overriding Interface Implementations


8.3. Overriding Interface Implementations

An implementing class is free to mark any or all of the methods that implement the interface as virtual. Derived classes can override these implementations to achieve polymorphism. For example, a Document class might implement the IStorable interface and mark the Read() and Write() methods as virtual. The Document might Read() and Write( ) its contents to a File type. The developer might later derive new types from Document, such as a Note or EmailMessage type, and he might decide that Note will read and write to a database rather than to a file.

Example 8-4 strips down the complexity of Example 8-3 and illustrates overriding an interface implementation. The Read() method is marked as virtual and implemented by Document. Read() is then overridden in a Note type that derives from Document.

Example 8-4. Overriding an interface implementation
#region Using directives using System; using System.Collections.Generic; using System.Text; #endregion namespace overridingInterface {    interface IStorable    {       void Read( );       void Write( );    } // Simplify Document to implement only IStorable    public class Document : IStorable    {       // the document constructor       public Document( string s )       {          Console.WriteLine(             "Creating document with: {0}", s );       }       // Make read virtual       public virtual void Read( )       {          Console.WriteLine(             "Document Read Method for IStorable" );       }       // NB: Not virtual!       public void Write( )       {          Console.WriteLine(             "Document Write Method for IStorable" );       }    } // Derive from Document    public class Note : Document    {       public Note( string s ):       base(s)       {          Console.WriteLine(             "Creating note with: {0}", s );       }       // override the Read method       public override void Read( )       {          Console.WriteLine(             "Overriding the Read method for Note!" );       }       // implement my own Write method       public new void Write( )       {          Console.WriteLine(             "Implementing the Write method for Note!" );       }    }    public class Tester    {       static void Main( )       {          // create a document reference to a Note object          Document theNote = new Note( "Test Note" );          IStorable isNote = theNote as IStorable;          if ( isNote != null )          {             isNote.Read( );             isNote.Write( );          }          Console.WriteLine( "\n" );          // direct call to the methods          theNote.Read( );          theNote.Write( );          Console.WriteLine( "\n" );          // create a note object          Note note2 = new Note( "Second Test" );          IStorable isNote2 = note2 as IStorable;          if ( isNote2 != null )          {             isNote2.Read( );             isNote2.Write( );          }          Console.WriteLine( "\n" );          // directly call the methods          note2.Read( );          note2.Write( );       }    } } Output: Creating document with: Test Note Creating note with: Test Note Overriding the Read method for Note! Document Write Method for IStorable Overriding the Read method for Note! Document Write Method for IStorable Creating document with: Second Test Creating note with: Second Test Overriding the Read method for Note! Document Write Method for IStorable Overriding the Read method for Note! Implementing the Write method for Note!

In this example, Document implements a simplified IStorable interface (simplified to make the example clearer):

interface IStorable {     void Read();     void Write( ); }

The designer of Document has opted to make the Read() method virtual, but not to make the Write( ) method virtual:

public virtual void Read()

In a real-world application, if you were to mark one as virtual, you would almost certainly mark both as virtual, but I've differentiated them to demonstrate that the developer is free to pick and choose which methods are made virtual.

The Note class derives from Document:

public class Note : Document

It's not necessary for Note to override Read(), but it is free to do so and has in fact done so here:

public override void Read()

In Tester, the Read and Write methods are called in four ways:

  • Through the base class reference to a derived object

  • Through an interface created from the base class reference to the derived object

  • Through a derived object

  • Through an interface created from the derived object

To accomplish the first two calls, a Document (base class) reference is created, and the address of a new Note (derived) object created on the heap is assigned to the Document reference:

Document theNote = new Note("Test Note");

An interface reference is created and the as operator is used to cast the Document to the IStorable reference:

IStorable isNote = theNote as IStorable;

You then invoke the Read() and Write( ) methods through that interface. The output reveals that the Read() method is responded to polymorphically and the Write( ) method is not, just as we would expect:

Overriding the Read method for Note! Document Write Method for IStorable

The Read( ) and Write( ) methods are then called directly on the object itself:

theNote.Read(); theNote.Write();

and once again you see the polymorphic implementation has worked:

Overriding the Read method for Note! Document Write Method for IStorable

In both cases, the Read( ) method of Note is called and the Write() method of Document is called.

To prove to yourself that this is a result of the overriding method, next create a second Note object, this time assigning its address to a reference to a Note. This will be used to illustrate the final cases (i.e., a call through a derived object and a call through an interface created from the derived object):

Note note2 = new Note("Second Test");

Once again, when you cast to a reference, the overridden Read( ) method is called. When, however, methods are called directly on the Note object:

note2.Read(); note2.Write();

the output reflects that you've called a Note and not an overridden Document:

Overriding the Read method for Note! Implementing the Write method for Note!



Programming C#(c) Building. NET Applications with C#
Programming C#: Building .NET Applications with C#
ISBN: 0596006993
EAN: 2147483647
Year: 2003
Pages: 180
Authors: Jesse Liberty

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net