I really like the way things are explained in the Ninject documention, so I'll just use their examples. You can always read the full documentation here: https://github.com/ninject/ninject/wiki/_pages
Let's say you have a Sword class like this:
class Sword
{
public void Hit(string target)
{
Console.WriteLine("Chopped {0} clean in half", target);
}
}
The sword can hit something. Now suppose you have a Samurai class. This Samurai class uses a Sword to attack.
class Samurai
{
private Sword _sword;
public Samurai()
{
_sword = new Sword();
}
public void Attack(string target)
{
_sword.Hit(target);
}
}
This all works nice and fine like this:
class Program
{
public static void Main()
{
Samurai warrior = new Samurai();
warrior.Attack("the evildoers");
}
}
You now have a Samurai class that is tightly coupled to the Sword class. What when you want to have an army of Samurai? Some use a Sword, some use BowAndArrow and some use a Shuriken. You would have to modify your Samurai class each time you add a new weapon. Because that's what a Sword, a BowAndArrow and a Shuriken are. They are all weapons that the Samurai can use to Hit something.
This is where interfaces come in play. Let's abstract out the functionality of attacking with a weapon using an interface:
interface IWeapon
{
void Hit(string target);
}
class Sword : IWeapon
{
public void Hit(string target)
{
Console.WriteLine("Chopped {0} clean in half", target);
}
}
class BowAndArrow : IWeapon
{
public void Hit(string target)
{
Console.WriteLine("Shot {0} right in the chest!", target);
}
}
class Shuriken : IWeapon
{
public void Hit(string target)
{
Console.WriteLine("Pierced {0}'s armor", target);
}
}
What we have now is an interface IWeapon and three classes implementing that interface. The interface acts like a contract. It says "If you implement me, you must provide the Hit method. That methods should accept a string parameter and shouldn't return anything".
What does that change for our Samurai? Instead of being coupled to class Sword, it can now use the interface IWeapon like this:
class Samurai
{
private IWeapon _weapon;
public Samurai(IWeapon weapon)
{
_weapon = weapon;
}
public void Attack(string target)
{
_weapon.Hit(target);
}
}
Now the Samurai class uses an IWeapon. Because each class implementing the IWeapon interface agrees to the contract of providing the Hit method, the Samurai class doesn't need to know or care what weapon it is wielding. It just knows that it has a weapon and it can Hit with is.
Like this:
class Program
{
public static void Main()
{
Samurai warrior1 = new Samurai(new Sword());
Samurai warrior2 = new Samurai(new Shuriken());
Samurai warrior3 = new Samurai(new BowAndArrow());
warrior1.Attack("the evildoers");
warrior2.Attack("the big guy in front");
warrior3.Attack("the scared guy running away");
}
}
I hope this makes some sense.