.NET
  Home arrow .NET arrow Page 4 - Delving Deeper into Interface-Based Progra...
ASP Free Forums 
.NET  
ASP  
ASP Code  
ASP.NET  
ASP.NET Code  
BrainDump  
C#  
Code Examples  
Database  
Database Code  
IIS  
Microsoft Access  
MS SQL Server  
Visual Basic.NET  
Windows Scripting  
Windows Security  
XML  
ASP Web Hosting  
ASP.NET Web Hosting 
Dedicated Servers 
Moblin 
JMSL Numerical Library 
Windows Web Hosting
 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
.NET

Delving Deeper into Interface-Based Programming
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 2
    2007-05-31

    Table of Contents:
  • Delving Deeper into Interface-Based Programming
  • Interfaces and Partial Types
  • Implementing Multiple Interfaces
  • Interfaces and Class Hierarchies

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Delving Deeper into Interface-Based Programming - Interfaces and Class Hierarchies


    (Page 4 of 4 )

    In component-oriented programming, you focus on defining and implementing interfaces. In object-oriented programming, you model your solution by using class hierarchies. How do the two concepts interact? The answer depends on the way you override or redefine the interface methods at the different levels of the class hierarchy. Consider the code in Example 3-9, which illustrates that when defining an interface only at the root of a class hierarchy, each level must override its base-class declarations to preserve semantics.

    Example 3-9. Overriding an interface in a class hierarchy

    using System.Diagnostics;//For the Trace class

    public interface ITrace
    {
     
    void TraceSelf();
    }
    public class A : ITrace
    {
     
    public virtual void TraceSelf()
     
    {
       
    Trace.WriteLine("A");
     
    }
    }
    public class B : A
    {
     
    public override void TraceSelf()
     
    {
       
    Trace.WriteLine("B");
     
    }
    }
    public class C : B
    {
     
    public override void TraceSelf() 
      {
        Trace.WriteLine("C");
      }
    }

    In a typical class hierarchy, the topmost base class should derive from the interface, providing polymorphism with the interface to all subclasses. The topmost base class must also define all the interface members asvirtual, so that subclasses can override them. Each level of the class hierarchy can override its preceding level (using theoverride inheritance qualifier), as shown in Example 3-9. When the client uses the interface, it then gets the desired interpretation of the interface. For example, if the client code is:


    C# Inheritance Directives

    In C#, you are required to explicitly indicate the semantics of inheritance when you supply a method with a name and signature identical to those of a base-class method. If you wish to override the base-class method when instantiating a base-class type with a subclass reference, you need to use the override directive:

      public class BaseClass
      {
        public virtual void TraceSelf()
        {
         
    Trace.WriteLine("BaseClass");
       
    }
      }
      public class SubClass : BaseClass
      {
       
    public override void TraceSelf()
        {
          Trace.WriteLine("SubClass");
       
    }
      }
      BaseClass obj = new SubClass();
      obj.TraceSelf(); //Outputs "SubClass"

    If you want to provide the base-class behavior instead, use thenewdirective, with or withoutvirtual, at the base class:

      public class BaseClass
     
    {
        public virtual void TraceSelf()
        {
         
    Trace.WriteLine("BaseClass");
       
    }
      }
      public class SubClass : BaseClass
      {
       
    public new void TraceSelf()
        {
          Trace.WriteLine("SubClass");
        }
      }
      BaseClass obj = new SubClass();
      obj.TraceSelf(); //Outputs "BaseClass "


      ITrace obj = new B();
      obj.TraceSelf();

    the object traces “B” to the output window, as expected.

    Things are less obvious if the subclasses use thenewinheritance qualifier. Thenewmodifier gives subclass behavior only when dealing with an explicit reference to a subclass, such as:

      B obj = new B();

    In all other cases, the base class implementation is used. If the code in Example 3-9 was written as:

      public class A : ITrace
     
    {
       
    public virtual void TraceSelf()//virtual is optional
       
    {
         
    Trace.WriteLine("A");
       
    }
      }
      public class B : A
      {
       
    public new void TraceSelf()
       
    {
         
    Trace.WriteLine("B");
       
    }
      }
      public class C : B
      {
       
    public new void TraceSelf()
        {
          Trace.WriteLine("C");
        }
      }

    then this client code:

      ITrace obj = new B();
      obj.TraceSelf();

    would now trace “A” to the output window instead of “B.” Note that this is exactly why thenew inheritance modifier is available. Imagine a client that somehow depends on the base class’s particular implementation. If a new subclass is used instead of the base class, thenewmodifier ensures that the client will get the implementation it expects. However, this nuance makes sense only when you’re dealing with clients that don’t use interface-based programming but rather program directly against the objects:

      A obj = new B();
      obj.TraceSelf();//Traces "A"

    You can support such clients and still provide interface-based services to the rest of the clients. To achieve that, each class in the hierarchy can reiterate its polymorphism with the interface by explicitly deriving from the interface (in addition to having the base class derive from the interface). Doing so (as shown in Example 3-10) makes thenewmodifier yield the same results as theoverridemodifier for the interface-based clients:

      ITrace obj = new B();
      obj.TraceSelf();//Traces "B"

    Note that usingvirtualat the base-class level is optional.

    In general, you should use theoverridemodifier, as in Example 3-9, with virtual interface members at the topmost base class. Such code is readable and straightforward. Code such as that in Example 3-10 makes for an interesting exercise but is rarely of practical use.

    Example 3-10.  Deriving from the interface explicitly at each level of the class hierarchy

    using System.Diagnostics;//For the Trace class

    public interface ITrace
    {
     
    void TraceSelf();
    }
    public class A : ITrace
    {
     
    public virtual void TraceSelf()//virtual is optional
      {
        Trace.WriteLine("A");
      }
    }
    public class B : A,ITrace
    {
     
    public new void TraceSelf() 
      {
        Trace.WriteLine("B");

      }
    }
    public class C : B,ITrace
    {
     
    public new void TraceSelf()
      {
        Trace.WriteLine("C");
      }
    }

    If you want to combine explicit interface implementation and class hierarchy, you should do so in a way that allows a subclass to call its base-class implementation. Because with explicit interface implementation, the implementation is private, you will need to add at the topmost base class a protected virtual method for each interface method. Only the topmost base class should explicitly implement the interface, and its implementation should call the protected virtual methods. All the subclasses should override the protected virtual methods:

      public class A : ITrace
     
    {
        protected virtual void TraceSelf()
        {
         
    Trace.WriteLine("A");
        }
        void ITrace.TraceSelf()
        {
         
    TraceSelf();
       
    }
      }
      public class B : A
      {
       
    protected override void TraceSelf()
        {
          Trace.WriteLine("B");
          base.TraceSelf();
       
    }
      }

    Please check back next week for the continuation of this article.


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

       · This article is an excerpt from the book "Programming .NET Components, Second...
     

    Buy this book now. This article is excerpted from chapter three of Programming .NET Components, Second Edition, written by Juval Lowy (O'Reilly, 2006; ISBN: 0596007620). Check it out today at your favorite bookstore. Buy this book now.

    .NET ARTICLES

    - More on Commands, Input and the WPF
    - Grouping and Aggregating When Querying LINQ ...
    - Commands, Input and the WPF
    - Keyboard and Ink Input with WPF
    - Mouse Input and the WPF
    - Input with Windows Presentation Foundation
    - Introducing LINQ with XML and Databases
    - An Introduction to LINQ
    - Querying LINQ to SQL: Basics
    - Completing a Simple Storefront with LINQ
    - Knowing Your Environment: the System.Environ...
    - Creating the Home Page for a Simple Storefro...
    - LINQ Quickly with Language Integrated Queries
    - Introducing LINQ to SQL Designer using Visua...
    - Beginning LINQ to SQL Using Visual Studio 20...





    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 2 hosted by Hostway