The interface defines the contract. This is a promise that the object will behave in a certain way. Before exploring interfaces, you usually think about objects in specific terms. For example, suppose we have a list of products:
List<string> products = new List<string>() { "desktop", "laptop", "server" };
And we have a method that outputs our products:
void PrintProducts(List<string> products) { foreach (string product in products) { Console.WriteLine(product); } }
Our method is associated with a specific type of list. Does it need to be? There are many different types of collections in C #: lists, arrays, ReadOnlyCollection, etc. All you really need to do is cycle through them. There are many methods on the list that are not in the array, but you are not using them here. Fortunately, they all implement the IEnumerable interface. This means that they are all βcontractedβ so that they can be listed.
Method change as follows:
void PrintProducts(IEnumerable<string> products) { foreach (string product in products) { Console.WriteLine(product); } }
means that now you can pass an array, or a list, or some unique container that you yourself create.
Another example: suppose you have a data repository:
public class DatabaseRepository { public void AddProduct(Product product) {
And you have a class that needs this database:
public class ProductManager { DatabaseRepository _repository; public ProductManager(DatabaseRepository repository) { _repository= repository; } }
Unfortunately, this class is bound to your database. What to do if you decide to go to storage as an XML file or save it in some kind of storage of key cloud value values. You will have to modify the ProductManager, which is complex and error prone. Assume instead that we have defined an interface:
public interface IRepository { void AddProduct(Product product); }
Modifying our ProductManager class to use this interface:
public class ProductManager { IRepository _repository; public ProductManager(IRepository repository) { _repository= repository; } }
means that no matter what repository of this type, we know that there will always be an AddProduct (Product product) method. Now we can create our XML repository:
public class XMLRepository : IRepository { public void AddProduct(Product product) {
Now we can go to any repository:
ProductManager manager = new ProductManager(new DatabaseRepository())
or
ProductManager manager = new ProductManager(new XMLRepository())
and our ProductManager behaves exactly the same. He absolutely does not know what a particular type is.
This becomes very useful when you get into unit testing. Inversion of control is what you want to read when you get a clear idea of ββhow interfaces work.