Link to home
Start Free TrialLog in
Avatar of infotechelg
infotechelgFlag for United States of America

asked on

Why Interfaces?

Take a look at the follwing page about Interfaces from Microsoft:

http://msdn.microsoft.com/en-us/library/64syzecx.aspx

I'm really, really trying to see the benefit of interfaces but am failing to see their point.

Using the example at the bottom of the page, if I remove the ": IEmployee" from the "public class Employee : IEmployee" everything still works fine; making it seem to me that creating the interface is a waste of time and resources.

So, can anyone explain, in laymen's terms, why would I ever bother to create interfaces? If the answer is "it's good practice" then I will continue to not use them unless there is some substantial performance benefit.

Please shed some light...
// Why is any of this...
interface IEmployee
{
    string Name
    {
        get;
        set;
    }

    int Counter
    {
        get;
    }
}
//...necessary??

public class Employee : IEmployee // Remove : IEmployee and is still works
{
    public static int numberOfEmployees;

    private string name;
    public string Name  // read-write instance property
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }

    private int counter;
    public int Counter  // read-only instance property
    {
        get
        {
            return counter;
        }
    }

    public Employee()  // constructor
    {
        counter = ++counter + numberOfEmployees;
    }
}

class TestEmployee
{
    static void Main()
    {
        System.Console.Write("Enter number of employees: ");
        Employee.numberOfEmployees = int.Parse(System.Console.ReadLine());

        Employee e1 = new Employee();
        System.Console.Write("Enter the name of the new employee: ");
        e1.Name = System.Console.ReadLine();

        System.Console.WriteLine("The employee information:");
        System.Console.WriteLine("Employee number: {0}", e1.Counter);
        System.Console.WriteLine("Employee name: {0}", e1.Name);
    }
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of infotechelg

ASKER

"You can't see the benefit because that is a horrible example!  =\"

Ha! Thanks, Microsoft.

I'll look over both of your responses carefully.
jensfiederer & Idle_Mind,

both of your responses make sense. Do you have any real-life examples (code) that you could share? I'm more of a visual learner (hence the reason why the Microsoft Example was so bad!).

Cheers,
Jeremy
My example WAS a real-life example, it's something I had to do just a couple of weeks ago - it was actually DrawFilter, not DisplayFilter though.


Here is a story from one person who did something similar:

http://forums.infragistics.com/forums/p/21808/79342.aspx

A simpler example than Infragistics would be in existing .NET code....

the Sort method on generic collections such as list allows you to pass in an "IComparer".

YOU can write the class/method that does it, it just has to conform to the IComparer interface.
I know it was. I meant does any one have any CODE examples of this working in real life so i can see how it works.
Thanks for your insight. This should get me on the right track.
Maybe this silly example will help...

Not that each type of pet has its own unique abilities, and other than the Interface, have nothing else in common.

The code in Main() is ONLY using the Interface Type, yet we are able to interact with all these disparate types in the same way; asking each to "speak".  We could add an infinite number of other animals, even from outside sources as jensfiederer points out, and the base code would not change.  We don't care what the actual underlying type of the animal is as long as it satisfies the conditions of our Animal Interface.

Also note that the classes could implement any number of other Interfaces as well and it wouldn't change the code in this project.  This is typically how we get around the fact that .Net does not allow multiple inheritance.

Anyhoo, here's the sample code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {

        static void Main(string[] args)
        {
            List<Animal> animals = new List<Animal>();
            animals.Add(new Dog());
            animals.Add(new Cat());
            animals.Add(new Snake());
            animals.Add(new Fish());

            foreach (Animal pet in animals)
            {
                Console.WriteLine(pet.Speak());
            }

            Console.WriteLine("Press enter to quit.");
            Console.ReadLine();
        }

    }

    interface Animal
    {
        string Speak();
    }
    
    public class Dog : Animal
    {

        string Animal.Speak()
        {
            return "Woof!";
        }

        public void PeeOnFloor()
        {
            Console.WriteLine("Unexpected output!");
        }

    }

    public class Cat : Animal
    {

        string Animal.Speak()
        {
            return "Meow!";
        }

        public void EatHousePlants()
        {
            Console.WriteLine("Unexpected input!");
        }

    }

    public class Snake : Animal
    {

        string Animal.Speak()
        {
            return "Hiss!";
        }

        public void BiteOwner()
        {
            Console.WriteLine("Invalid action attempted!");
        }

    }

    public class Fish : Animal
    {

        string Animal.Speak()
        {
            return "Bloop!";
        }

        public void PeformAcrobatics()
        {
            Console.WriteLine("Floating upside down isn't a trick!");
        }

    }

}

Open in new window

Here's my attempt at a "real-world" example  : )


Think about water faucets. How do you turn them on? Some single dials that spin; some have two handles, one for each temperature, some have chains that you pull to turn on the water. All of these designs have the same operations in common--turn water on; turn water off. These operations could thusly be defined in an interface.

interface IFaucet
{
    void TurnOnWater();
}

Open in new window


This interface is the contract between any class that implements IFaucet. This contract says, "if you implement IFaucet, then you WILL have two functions called 'TurnOnWater' and 'TurnOffWater.' Because you know that an IFaucet has these two methods, any class that implements IFaucet should have these two methods.

The wonderful thing about interfaces is that you don't care how, in this particular example, a faucet turns on the water; only that it does so. So for each class that implements IFaucet, we can different concepts of turning water on and off. For example:

Chain Faucet
class ChainFaucet : IFaucet
{
    enum ChainState
    {
        ChainPulled,
        ChainReleased,
    }

    private ChainState _state;

    #region IFaucet Members

    public void TurnOnWater()
    {
        this._state = ChainState.ChainPulled;
    }

    public void TurnOffWater()
    {
        this._state = ChainState.ChainReleased;
    }

    #endregion
}

Open in new window


DualKnobFaucet
class DualKnobFaucet : IFaucet
{
    private bool _hotKnob;
    private bool _coldKnob;

    #region IFaucet Members

    public void TurnOnWater()
    {
        this._hotKnob = true;
        this._hotKnob = true;
    }

    #endregion

    #region IFaucet Members


    public void TurnOffWater()
    {
        this._hotKnob = false;
        this._hotKnob = false;
    }

    #endregion
}

Open in new window


Single Knob Faucet
class SingleKnobFaucet : IFaucet
{
    private int _degreesFromOff;

    #region IFaucet Members

    public void TurnOnWater()
    {
        this._degreesFromOff = 30;
    }

    public void TurnOffWater()
    {
        this._degreesFromOff = 0;
    }

    #endregion
}

Open in new window


So just as when you use the sink in your bathroom, you don't care how the faucet allows water to start flowing; you only care that it does allow water to flow. Each faucet implementation above turns on the water in its own special way, but to the outside world, we only know that the faucet turns water on and turns water off.

Also with interfaces, you get the benefit of treating each implementation of IFaucet generically, that is, as an IFaucet rather than, for instance, a DualKnobFaucet. This allows your code to be more abstract. This is akin to saying, "honey, will you turn off the faucet," rather than saying, "honey, will you turn off the dual-knob faucet?" Both mean the same thing, but in the former you are referring to the generic name. This comes in handy in code as well at times.
IFaucet above should have been defined as this:
interface IFaucet
{
    void TurnOnWater();

    void TurnOffWater();
}

Open in new window

Both mean the same thing...

I should rephrase this as, "Both accomplish the same goal..."
Wow, thanks a lot everyone!
Going back to the inheritance issue, both of these problems could have been solved by creating a base type of Faucet or Animal, and then the Derived class could have provided its own specialized way of accomplishing the task at hand by Overriding the base code.

***BUT*** since you can only Inherit from ONE Class, this limits what we can do in some cases.  If either of the classes in these scenarios were required to have already been derived from some other class...we would be screwed.  By using the Interface approach we can now allow the class to Inherit from something else while still being able to be treated as our Interface type.

Remember, you can Implement as many Interfaces as you want, but can only Inherit from one thing.
It's very interesting question. And all programmers ask it sooner or later.

Please see the discussion. BTW, the answer from Idle Mind was accepted - he know all about interfacers :)

In the discussion above I had some examples, but the question was asked back:

"...class MyTest : ICompareable ()

I would have methods in there like for example:

Public int CompareTo

Now, I can have that as well without the need for the Interface. "

Yes, we may create a class and put CompareTo method without interfaces. But it has no use.
Say, you put objects of your class to a list and want to sort them. How you can do this? OK, if List can see that your class implements IComparable, it can call CompareTo method and sort your objects. If your class does not implement IComparable, the List has NO idea how to sort your objects (it simply can't find CompareTo method that does not belong to a IComparable  interface. Result - can't sort objects.

This is just one example. Again - see the discussion above and more from Idle Mind and me :)
Ha, guys, you're quick :)

People love interfaces! :)
By using the Interface approach we can now allow the class to Inherit from something else while still being able to be treated as our Interface type.

Technically speaking, we are not inheriting anything from the interface since interfaces can't have any members of their own--you don't even define access modifiers for the methods/properties listed in the interface--but for the sake of this discussion you can think of it as inheriting.
Thanks a ton, everybody. I really appreciate it.
@Idle_Mind

Please don't think I was taking a shot at you in http:#35264305 ...  I just wanted to delineate the difference between inheriting a base class and implementing an interface  : )
No problem...  =)

I was thinking more along the lines of something like below where the class already Inherits from something else...but we can still Implement as many Interfaces as we want:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {

        static void Main(string[] args)
        {
            BaseClass bc = new DerivedClass();

            Console.WriteLine(bc.Speak());
            ((SomeInterface1)bc).SomeAction();
            ((SomeInterface2)bc).SomeOtherAction();

            Console.WriteLine("Press enter to quit.");
            Console.ReadLine();
        }

    }

    public class BaseClass
    {
        public virtual string Speak()
        {
            return "Hello World!";
        }
    }

    interface SomeInterface1
    {
        void SomeAction();
    }


    interface SomeInterface2
    {
        void SomeOtherAction();
    }

    public class DerivedClass : BaseClass, SomeInterface1, SomeInterface2
    {

        public override string Speak()
        {
            return "Hello Derived World!";
        }

        void SomeInterface1.SomeAction()
        {
            Console.WriteLine("SomeAction()");
        }

        void SomeInterface2.SomeOtherAction()
        {
            Console.WriteLine("SomeOtherAction()");
        }

    }

}

Open in new window