Now you most likely do not need it, you will come up with it sometime later, when you are ready. Do not bother and go further, very often programmers are forced to skip topics and return to them. The main thing is that you know that there is such a thing as an interface, and it allows you to hide real implementations of classes.
With the help of interfaces you:
- Do not tie the logic of your application with specific classes and you can easily make changes to one class, without touching others, adding functionality or replacing one class with another, without touching the whole application. That is, an abstraction from the implementation is implemented;
- you can design the application logic on the interfaces, leaving the implementation for later and using the stubs;
- apply the so-called multiple inheritance;
- if you are a boss, you can easily convey your thoughts to subordinates (implement me the functionality of this interface here).
I will give a few examples in which the interface is used, but at once I make a reservation, they are not the best representatives. After all, I am also studying. )
Design of a non-zoo
Let's design a small program of the zoo, while the zoo we will step by step.
1. First of all, it is worth populating animals that can walk on it, let's get started.
To describe the zoo life cycle, I use the ZooLivecycle class:
class ZooLivecycle { public void allPetWalk() { } }
So, we have animals that can walk, let's define their capabilities through interfaces and implement them.
interface IWalk { void walk(); } class Cat : IWalk { public void walk() { Console.WriteLine("cat walk"); } } class Dog : IWalk { public void walk() { Console.WriteLine("dog walk"); } } class Fish : IWalk { public void walk() { Console.WriteLine("fish cant walk"); } } class Bird : IWalk { public void walk() { Console.WriteLine("bird can fly"); } }
In order for all animals to go, it is easier to transfer them to the zoo class by the whole array and walk through them in a cycle.
class ZooLivecycle { public void allPetWalk(IWalk[] arr) { for (int i = 0; i < arr.Count(); i++) arr[i].walk(); } }
So now we can call our implementation.
class Program { static void Main(string[] args) { ZooLivecycle zoo = new ZooLivecycle(); IWalk[] walks = new IWalk[]{new Cat(), new Dog(), new Fish(), new Bird()}; Console.WriteLine("\n*Pet Walk*"); zoo.allPetWalk(walks); Console.Read(); } }
And now try to implement it without interfaces, mainly the allPetWalk function, although there is a way - this is a common parent class. You can also try to pass the link as public void allPetWalk(Object[] arr)
and then public void allPetWalk(Object[] arr)
types, but this is a very bad practice, since you lose control over the types and have to add checks that are not the best solution.
2. Go ahead, we decided to add a surveillance system, namely a video camera that can transmit information.
interface IObservation { void analyze(); } class Videocamera : IObservation { public void analyze() { Console.WriteLine("In zoo all ok"); } }
We sell information in the zoo classroom:
class ZooLivecycle { public void allPetWalk(IWalk[] arr) { for (int i = 0; i < arr.Count(); i++) arr[i].walk(); } public void zooAnalyze(IObservation[] arr) { for (int i = 0; i < arr.Count(); i++) arr[i].analyze(); } }
Well, the challenge.
class Program { static void Main(string[] args) { ZooLivecycle zoo = new ZooLivecycle(); IWalk[] walks = new IWalk[]{new Cat(), new Dog(), new Fish(), new Bird()}; IObservation[] analyze = new IObservation[] { new Videocamera() }; Console.WriteLine("\n*Pet Walk*"); zoo.allPetWalk(walks); Console.WriteLine("\n*Analyze zoo*"); zoo.zooAnalyze(analyze); Console.Read(); } }
3. And now let's poddle a pig if someone still used the parent class instead of interfaces.
We implement an assistant who can both walk around the zoo and transmit information. In C #, there is no cross-inheritance, but you can inherit multiple interfaces instead.
class HelperPet : IWalk, IObservation { public void walk() { Console.WriteLine("helppet walk"); } public void analyze() { Console.WriteLine("helppet analyze"); } }
That's all I had to add. You can continue to use our zoo, without rewriting anything.
class Program { static void Main(string[] args) { ZooLivecycle zoo = new ZooLivecycle(); IWalk[] walks = new IWalk[]{new Cat(), new Dog(), new Fish(), new Bird(), new HelperPet()}; IObservation[] analyze = new IObservation[] { new Videocamera(), new HelperPet() }; Console.WriteLine("\n*Pet Walk*"); zoo.allPetWalk(walks); Console.WriteLine("\n*Analyze zoo*"); zoo.zooAnalyze(analyze); Console.Read(); } }
Now let's look at real-life examples that are very often used.
Very often, interfaces are used as descriptive models, the inheritance from which makes it possible to work with what they are created for. Thus, you are not tied to specific classes. In the language itself, C # even has interfaces that implement this or that behavior. You will often encounter this if you go to a WPF or ASP.NET MVC application.
Using foreach with own classes
Let's improve our zoo and add an animal storage class. Despite the fact that it is rather voluminous, I just took an example from MSDN and just substituted my values.
public interface IWalk { void walk(); } public class Animals : IEnumerable<IWalk> { private IWalk[] _pets; public Animals(IWalk[] pArray) { _pets = new IWalk[pArray.Length]; for (int i = 0; i < pArray.Length; i++) { _pets[i] = pArray[i]; } } IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)GetEnumerator(); } public PetsEnum GetEnumerator() { return new PetsEnum(_pets); } IEnumerator<IWalk> IEnumerable<IWalk>.GetEnumerator() { return (IEnumerator<IWalk>)GetEnumerator(); } } public class PetsEnum : IEnumerator { public IWalk[] _pets; int position = -1; public PetsEnum(IWalk[] list) { _pets = list; } public bool MoveNext() { position++; return (position < _pets.Length); } public void Reset() { position = -1; } object IEnumerator.Current { get { return Current; } } public IWalk Current { get { try { return _pets[position]; } catch (IndexOutOfRangeException) { throw new InvalidOperationException(); } } } } Теперь я могу делать так: class Program { static void Main(string[] args) { ZooLivecycle zoo = new ZooLivecycle(); Animals animals = new Animals(new IWalk[]{new Cat(), new Dog(), new Fish(), new Bird(), new HelperPet()}); Console.WriteLine("\n*Pet Walk*"); zoo.allPetWalk(animals); Console.Read(); } } class ZooLivecycle { public void allPetWalk(Animals animals) { foreach(IWalk animal in animals) animal.walk(); } }
Without implementing the interface, you cannot use foreach with your class, although in fact it is done very quickly. In this case, the foreach method works with any objects, and if there were no interfaces, it would be more difficult to achieve this effect. Now you can add methods such as Add, Remove, etc. to the Animals class.
Well, in the end, you can put the stub and transfer test data.
If the implementation of classes is quite complicated, for example, one of them receives data from the database, and the other processes this data, then you can write a fake class. That is, instead of real data, you transfer a class that does not use a connection to the database, and then it can be rewritten. Moreover, it is possible to work normally both with one and with another class alternately.