Creating and implementing an interface

For many developers, interfaces are confusing and their purpose not clearly understood. Interfaces are actually quite easy to get to grips with once you understand the concept that defines an interface.

Interfaces act like verbs. So, for example, if we had to create two classes called Lion and Tiger that derive from the Cat abstract class, the interface would describe some sort of action. Lions and tigers can roar (but not purr). We can then create an interface called IRoarable. If we had to derive a class called Cheetah from our abstract class Cat, we would not be able to use the IRoarable interface, because cheetahs purr. We would need to create an IPurrable interface.

Getting ready

Creating an interface is very similar to creating an abstract class. The difference is that the interface is describing what the class can do, in the case of the Cheetah class, by implementing IPurrable.

How to do it…

  1. If you haven't already done so in the previous recipe, create an abstract class called Cat:
    public abstract class Cat
    {
        public abstract void Eat();
        public abstract void Hunt();
        public abstract void Sleep();
    }
  2. Next, add a class called Cheetah that inherits from the Cat abstract class:
    public class Cheetah : Cat
    {
        
    }
  3. As soon as you inherit from the Cat abstract class, Visual Studio will show you a warning via the lightbulb feature. As you inherited from the abstract class Cat, you have to implement the abstract members within the abstract class in your derived class Cheetah:
    How to do it…
  4. This is easily fixable by typing Ctrl +. (period) and fixing all occurrences in the document. You can also do this for the project or solution. For our purpose, we only select the Document link at the bottom of the lightbulb suggestions. Visual Studio will automatically add the abstract methods defined in the abstract class to implement inside your Cheetah class:
    How to do it…
  5. You will notice that Visual Studio adds just the methods you need to override but will throw NotImplementedException if you try to use the class as is. The reason for using an abstract class is to implement the functionality defined in the abstract class Cat in the derived class Cheetah. Not doing so contravenes the rules for using abstract classes:
    public class Cheetah : Cat
    {
        public override void Eat()
        {
            throw new NotImplementedException();
        }
    
        public override void Hunt()
        {
            throw new NotImplementedException();
        }
    
        public override void Sleep()
        {
            throw new NotImplementedException();
        }
    }
  6. To add some implementation, modify your Cheetah class as follows. The implementation in the overridden methods is simple, but this validates the rule of writing some sort of implementation in the overridden methods:
    public class Cheetah : Cat
    {
        public override void Eat()
        {
            WriteLine($"The cheetah eats.");
        }
    
        public override void Hunt()
        {
            WriteLine($"The cheetah hunts.");
        }
    
        public override void Sleep()
        {
            WriteLine($"The cheetah sleeps.");
        }
    }

    Note

    You will notice that the following WriteLine method is used without the Console class. This is because we are using a new feature in C# 6.0 that allows developers to bring static classes into scope by adding the using static System.Console; statement to the top of your class file.

  7. Create an interface called IPurrable that will be implemented on the Cheetah class. A common naming convention for interfaces dictates that the interface name should be prefixed with a capital I:
    interface IPurrable
    {
    
    }
  8. Next, we will add a method to the interface that any class implementing the interface must implement. You will notice that the interface's SoftPurr method contains no implementation at all. It however specifies that we will need to pass this method an integer value for the decibel that the Cheetah class will purr at:
    interface IPurrable
    {
        void SoftPurr(int decibel);
    }
  9. The next step is to implement the IPurrable interface on the Cheetah class. To do this, we need to add the IPurrable interface name after the Cat abstract class name. If the Cheetah class did not inherit from the abstract class, then the interface name would simply follow after the colon:
    public class Cheetah : Cat, IPurrable
    {
        public override void Eat()
        {
            WriteLine($"The cheetah eats.");
        }
    
        public override void Hunt()
        {
            WriteLine($"The cheetah hunts.");
        }
    
        public override void Sleep()
        {
            WriteLine($"The cheetah sleeps.");
        }
    }
  10. After specifying that the Cheetah class implements the IPurrable interface, Visual Studio once again displays a warning via the lightbulb feature. It is warning us that the Cheetah class does not implement the SoftPurr method defined in the interface IPurrable:
    How to do it…
  11. As we did earlier, we can let Visual Studio suggest possible fixes for the problems encountered by typing Ctrl + . (period). Visual Studio suggests that the interface can be implemented implicitly or explicitly:
    How to do it…
  12. Knowing when to use an implicit or explicit implementation is also quite easy. We first need to know when using one over the other would be preferred. Let's start off by implementing the SoftPurr method implicitly by selecting the first option in the lightbulb suggestion. You will see that by selecting to implement the SoftPurr method defined in the IPurrable interface implicitly, adds it as if it were part of the Cheetah class:
    public class Cheetah : Cat, IPurrable
    {
        public void SoftPurr(int decibel)
        {
            throw new NotImplementedException();
        }
    
        public override void Eat()
        {
            WriteLine($"The cheetah eats.");
        }
    
        public override void Hunt()
        {
            WriteLine($"The cheetah hunts.");
        }
    
        public override void Sleep()
        {
            WriteLine($"The cheetah sleeps.");
        }
    }
  13. If we look at the SoftPurr method, it looks like a normal method inside the Cheetah class. This would be fine unless our Cheetah class already contains a property called SoftPurr. Go ahead and add a property called SoftPurr to your Cheetah class:
    public class Cheetah : Cat, IPurrable
    {
        public int SoftPurr { get; set; }
        
        public void SoftPurr(int decibel)
        {
            throw new NotImplementedException();
        }
    
        public override void Eat()
        {
            WriteLine($"The cheetah eats.");
        }
    
        public override void Hunt()
        {
            WriteLine($"The cheetah hunts.");
        }
    
        public override void Sleep()
        {
            WriteLine($"The cheetah sleeps.");
        }        
    }
  14. Visual Studio immediately displays a warning by telling us that the Cheetah class already contains a definition for SoftPurr:
    How to do it…
  15. It is here that the use of an explicit implementation becomes evident. This specifies that the SoftPurr method is a member of the implementation defined in the IPurrable interface:
    How to do it…
  16. Therefore, selecting the second option to implement the interface explicitly will add the SoftPurr method to your Cheetah class as follows:
    public class Cheetah : Cat, IPurrable
    {
        public int SoftPurr { get; set; }
    
        void IPurrable.SoftPurr(int decibel)
        {
            throw new NotImplementedException();
        }
    
        public override void Eat()
        {
            WriteLine($"The cheetah eats.");
        }
    
        public override void Hunt()
        {
            WriteLine($"The cheetah hunts.");
        }
    
        public override void Sleep()
        {
            WriteLine($"The cheetah sleeps.");
        }        
    }

    The compiler now knows that this is an interface that is being implemented and is therefore a valid line of code.

  17. For the purpose of this book, let's just use the implicit implementation. Let's write some implementation for the SoftPurr method and use the new nameof keyword in C# 6.0, as well as the interpolated string for the output. Also, remove the SoftPurr property added earlier:
    public void SoftPurr(int decibel)
    {
        WriteLine($"The {nameof(Cheetah)} purrs at {decibel} decibels.");
    }
  18. Heading over to our console application, we can call our Cheetah class as follows:
    Cheetah cheetah = new Cheetah();
    cheetah.Hunt();
    cheetah.Eat();
    cheetah.Sleep();
    cheetah.SoftPurr(60);
    Console.ReadLine();
  19. Running the application will produce the following output:
    How to do it…

How it works…

So, you might be wondering what the difference between an abstract class and an interface is. It basically comes down to where you want your implementation. If you need to share functionality between derived classes, then an abstract class is the best fit for your needs. In other words, we had specific things that were common to all cats (lions, tigers, and cheetahs) such as hunting, eating, and sleeping. This is then best used within an abstract class.

If your implementation is specific to a class or several classes (but not all classes), then your best course of action would be to use an interface. In this case, the IPurrable interface can be applied to several classes (for example, cheetahs and domestic cats) but can't be applied to all cats (such as lions and tigers), because not all cats can purr.

Knowing this difference and where you need to place your implementation will aid you in deciding whether you need to use an abstract class or an interface.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset