Thursday 1 October 2015

Interface

An interface defines a schema for a class to implement. It defines methods, properties, and events that a class must have, but does not provide an implementation for them. Interfaces can be used to define a common set of functionality that multiple classes can share, and to create loosely-coupled code. A class that implements an interface must provide an implementation for all of the members defined in the interface. Interfaces can also be inherited by other interfaces, allowing for a hierarchy of interfaces to be created.

For example we can define what properties and functions a student should have.


    interface IStudent
    {
        int StudentNumber { get; }
        IList<decimal> Grades {get; set;}
        decimal CalculateGPA();
    }


The above interface represents a student, notice that it's name starts with an I for IStudent, this is an accepted practice in c#. As you can see there is no implementation for any of its' members, just a definition. Now let's say we have a person class.


    class Person
    {
        private string _firstName;
        public string FirstName
        {
            get { return _firstName; }
            set
            {
                _firstName = CheckName(value);
            }
        }

        private string _lastName;
        public string LastName
        {
            get { return _lastName; }
            set { _lastName = CheckName(value); }
        }

        private string CheckName(string value)
        {
            if (Regex.IsMatch(value, @"^[a-zA-Z]{2,}$"))
                return value;
            throw new FormatException($"{value} is not a valid name");
        }

        public Person() {
            this._firstName = "";
            this._lastName = "";
         }

        public Person(string FirstName, string LastName) : this()
        {
            try
            {
                this.FirstName = FirstName;
                this.LastName = LastName;
            }
            catch (Exception ex)
            {
                throw new FormatException("A custom person exception", ex);
            }
        }
    }
   

we can use a combination of the person class and the IStudnet interface to create a student class.


    class Student : Person, IStudent
    {
        static int RunntingStudentNumber = 0;
        public IList<decimal> Grades { get; set; }
        public int StudentNumber { get; private set; } = RunntingStudentNumber++;

        public Student()
        {
            this.Grades = new List<decimal>();
        }

        public decimal CalculateGPA()
        {
            decimal total = 0;
            foreach (var g in Grades)
                total += g;
            return total / Grades.Count;
        }
    }


now  you may be wondering why did we bother with the interface, well there's multiple benefits from leveraging interfaces, we leveraged the IStudent interface this time because of the first point which we'll talk about further in Faking inheritance.
  • Multiple Inheritance: C# doesn't allow you to inherit from multiple classes but it does let you implement multiple interfaces allowing us to sort of fake it.
  • Interface Based programming: Interface based programming allows us to separate our class implementation from the declaration. This can facilitate that different classes have the same interactive members allowing us to swap one class for another.
  • Inversion of control: is an established pattern, that is facilitated by Interface based declarations, it basically states that if a class needs to do anything other then its main function we should provide that function to the class.
The primary benefit of using interfaces is that they allow for loose coupling of code. Because an interface defines a contract for a class to implement, rather than providing an implementation itself, different classes can implement the same interface in different ways. This allows for more flexibility and reusable code, as a single interface can be implemented by multiple classes, each providing its own unique implementation, and then these classes can be swapped for one another without having to rewrite any code in their consumers.

Additionally, interfaces can be used to create more maintainable and testable code, as they encourage the separation of concerns. Interfaces allow you to define a specific set of functionality that a class must have, without worrying about how that functionality is implemented. This allows for easier modification of individual classes without affecting the rest of the system.



In short interfaces are not class definitions, they can be used to define what to expect, you can think of the interface as building plans, and the building as the actual class.