This is another item that has come up enough in recent weeks to warrant a post. Like my other post on constructors, this is one of those items that OO developers just "know", often right until they have to use it.
So, what is an interface? Its a blueprint or definition for a class, containing signatures for class features (properties, methods, and events). An interface has no behaviour itself and cannot be instantiated. The quote about interfaces that is heard most often comes from the C# language specification itself: "An interface defines a contract that can be implemented by classes and structs."
So, what is this contract? The contract between an interface and a class that implements said interface is pretty simple. The class' side of the contract is that the class must implement each feature (property, method, and event) that the interface defines, or the class must be declared abstract. The interface's side of the contract is that the interface is to be immutable.
If this is the sum of the knowledge you have about interfaces, then you are selling yourself a bit short when it comes to object-oriented programming and the power of interfaces. Interfaces help a programmer achieve Abstraction and Polymorphism, two pillars of object-oriented programming. Interfaces also help you future-proof your application. Let's consider the following . . .
The tradtional OO example is an HR one. You design an application to manage employees. You start with an Employee abstract class, defining some basic features and default behaviors, leaving the rest to be overridden in sub-classes. You create to concrete sub-classes, SalariedEmployee and HourlyEmployee, each with their own implementations of the pay calculations.
You have an associated system, Check Writing System, that generates paychecks. This system accepts an Employee type as input to its GenerateCheck method. This is good, because this is a nice polymorphic way to accept both of your Employee sub-types without have to write two seperate methods for it. And when business explands and you start to take on ContractEmployees, the CheckWriting System still doesn't need to be updated.
After analysis, everyone realizes that the Check Writing System writes checks (duh). Someone gets the idea of using it to write all checks for the company. A system getting re-purposed beyond its original design? I know, its far-fetched, but go with me here. The next thing to come down for a request is writing a check to the grounds keeper. The guy that mows the lawns isn't a SalariedEmployee or HourlyEmployee. You might be able to consider him as a ContractEmployee, but its kind of stretching it. And the next request is to write a check to the IRS for taxes due. Ok, they definitely arent an employee of any type. Let's rewind a little bit and look at this again, but with interfaces in mind.
Let's consider what the realtionship is between the HR System and the Check Writing System for the organization. We need to have checks written for our employees. The organization also wants to to reuse the Check Writing System to write checks for any item the business needs a check written for (charitiable donation, IRS, lawn service, et cetera). This is where the interface is going to come in.
We are going to create an interface, call it iPaymentData, and it will contain definition that is pertinent to making a payment (payee's name/address, amount of check, et cetera). We decorate our Employee abstract class with this interface and implement the proper behaviour for each downstream class. The Check Writing System is changed to accept iPaymentData types instead of Employee types. Now, we have decoupled the Check Writing System away from the Employee inheritence heirarchy. The interface is acting as a contract between the system the implments the interface (HR Employees) and the system that expects the interface (Check Writing). The contract in this case ensures that any object that implements iPaymentData will have behaviours (properties, methods, events) that are pertinent to this particular problem domain. Check Writing doesn't care about the underlying concrete types that it processes, as long as the objects sent to it implement the iPaymentData interface, and therefor could call iPaymentData.Amount or iPaymentData.PayeeName. You could also look at it as the interface acting as a proxy or mediator between two systems.
When the next system change comes in (write checks for utilities and building services), you don't have to be concerned with how to make Utilites and Building Services into Employees. Instead, you focus on the UtilityService object and just implement the iPaymentData interface. The Check Writing System doesn't have to be changed at all.