Two Interfaces. Same Method. Two meanings.

ppl-act-010 We’ve discussed interfaces before, but today I want to dig a little deeper.  I’m going to assume for now that you already know what an interface is and that you know how to implement one on a class.

But let’s assume for a bit that you have two interfaces that have exactly the same method declared in them but each implementation of the method has two entirely different meanings.  How do you code for this?

To make the question more concrete, let’s use a classic illustration.

Let’s assume that you have a Metric interface and an English interface and that each interface has a property called Height.  When you implement Metric on your class (Person), Height should return a Metric value.  When you implement English on your Person class, it should return the value in feet.  The English unit.

Obviously, you can’t implement this on the same method.  So what do you do?

You use the handles syntax.

Well, actually, there isn’t a handles keyword.  But that’s how the VB.NET guys handle it.  In CSharp, we have a syntax that says, “Don’t override the method with this name, instead make this method override that method.”  It’s actually pretty cool once you see it.

So, let’s set up our code.

First, our two interfaces:

public interface Metric
{
    int Height {get;set;}
}

public interface English
{
    int Height {get;set;}
}

and next our class:

public class Person : English, Metric
{
}

To implement a property Height that implements the English interface:

public class Person : English, Metric
{
    int m_englishHeight;
    int m_metricHeight;
    int English.Height
    {
        get{return m_englishHeight;}
        set{m_englishHeight = value;}
    }

    int Metric.Height
    {
        get { return m_metricHeight; }
        set { m_metricHeight = value; }
    }
}

And now, the code to create a person object and call the English or Metric Height:

Person p = new Person();
int englishHeight = ((English)p).Height;
int metricHeight = ((Metric)p).Height;

You’ll see that you must cast your Person object to either an English type or a Metric type before retrieving (or setting) height so that the runtime knows which method you want to call.  In fact, you can’t call English.Height or Metric.Height directly.  Try it.  It won’t even show up in intellisense.

If you want to have a default Height method on the Person class that returns the English unit, for example, you’d need to add another property, Height, to the Person class.

public int Height
{
    get { return ((English)this).Height; }
    set { ((English)this).Height = value; }
}

Which could be called like this:

int defaultHeight = p.Height;

So the full implementation of Person looks like this:

public class Person : English, Metric
{
    int m_englishHeight;
    int m_metricHeight;
    public int Height
    {
        get { return ((English)this).Height; }
        set { ((English)this).Height = value; }
    }

    int English.Height
    {
        get{return m_englishHeight;}
        set{m_englishHeight = value;}
    }

    int Metric.Height
    {
        get { return m_metricHeight; }
        set { m_metricHeight = value; }
    }
}

Related Post

6 Responses to “Two Interfaces. Same Method. Two meanings.”

Leave a Reply

Comment Policy:

  • You must verify your comment by responding to the automated email that is sent to your email address. Unverified comments will never show.Leave a good comment that adds to the conversation and I'll leave your link in.
  • Leave me pure spam and I'll delete it.
  • Leave a general comment and I'll remove the link but keep the comment.

Notify me of followup comments via e-mail

Bear