infotechelg
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...
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);
}
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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
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
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.
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.
ASKER
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.
ASKER
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:
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!");
}
}
}
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.
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
DualKnobFaucet
Single Knob Faucet
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.
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();
}
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
}
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
}
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
}
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();
}
Both mean the same thing...
I should rephrase this as, "Both accomplish the same goal..."
ASKER
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.
***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 :)
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! :)
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.
ASKER
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 : )
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:
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()");
}
}
}
ASKER
Ha! Thanks, Microsoft.
I'll look over both of your responses carefully.