#444 – Interfaces Can Inherit from Other Interfaces

An interface can inherit from other interfaces.  A class implementing an interface must then implement all members of all interfaces in the inheritance chain.

For example, assume that we have an INameAndMotto interface with Name and Motto properties.

    interface INameAndMotto
    {
        string Name { get; set; }
        string Motto { get; set; }
    }

Now we can inherit this interface when we define the IMoo interface.

    interface IMoo : INameAndMotto
    {
        void Moo();
        List<string> MooLog { get; set; }
    }

Now if we specify that the Cow class inherits from IMoo, it must implement all methods in both IMoo and INameAndMotto.

    public class Cow : IMoo
    {
        public string Name { get; set; }
        public string Motto { get; set; }

        public void Moo()
        {
            Console.WriteLine("Moo");
        }

        public List<string> MooLog { get; set; }
    }


#443 – An Interface Cannot Contain Fields

An interface can contain methods, properties, events or indexers.  It cannot contain fields.

    interface IMoo
    {
        // Methods
        void Moo();

        // Field not allowed - compile-time error
        string Name;

Instead of a field, you can use a property.

    interface IMoo
    {
        // Methods
        void Moo();

        // Name as a property is OK
        string Name { get; set; }

Interfaces don’t allow fields because they consist of a contract that is a list of methods, whose implementation is provided by a class. Properties are implemented as methods (get and set accessors), so they fit this model.  But fields are just data locations, so it doesn’t make sense to include them in an interface.

#442 – Explicit Interface Implementation Allows Duplicate Member Names

Let’s assume that a class implements more than one interface and there is a particular member that exists in both interfaces.  For example, let’s say that the Cow class implements both the IMoo and IMakeMilk interfaces and they each contain a property named Motto whose type is string.

To provide implementations for both IMoo.Motto and IMakeMilk.Motto, the Cow class must implement the interfaces explicitly, to distinguish between the two properties.

    public class Cow : IMoo, IMakeMilk
    {
        string IMoo.Motto
        {
            get { return "I moo because I want attention"; }
        }

        string IMakeMilk.Motto
        {
            get { return "Everyone should drink a little milk every day"; }
        }

        // Other Cow stuff
    }

We now must access these properties through their corresponding interfaces.

            Cow bossie = new Cow("Bossie", 12);

            // NOTE: bossie.Motto does not exist

            IMoo mooing = bossie;
            Console.WriteLine(mooing.Motto);

            IMakeMilk milking = bossie;
            Console.WriteLine(milking.Motto);

#441 – Implementing Interface Members Explicitly

When you implement interface members in a class, the members are normally accessible via either a reference to the class or a reference to the interface.

Cow bossie = new Cow("Bossie", 5);

bossie.Moo();

IMoo mooer = bossie;
mooer.Moo();

If you want interface members to be accessible only via the interface, you can implement an interface member explicitly, by prefixing the member name with the name of the interface.

    public class Cow : IMoo
    {
        void IMoo.Moo()
        {
            Console.WriteLine("Moo");
        }
    }

You can now only call this member using an interface variable.

            Cow bossie = new Cow("Bossie", 12);

            // Compile error: Cow does not contain a definition for 'Moo'
            bossie.Moo();

            // But we CAN access via IMoo
            IMoo mooStuff = bossie;
            mooStuff.Moo();

#440 – A Class Can Implement More than One Interface

It’s possible for a class to implement more than one interface.

For example, a Cow class might implement both the IMoo and the IMakeMilk interfaces.  Multiple interfaces are listed after the class declaration, separated by commas.

    public class Cow : IMoo, IMakeMilk
    {
        public void Moo() { // do mooing here }
        public double Milk() { // do milking here }
    }

You can now use an instance of the Cow class to access members of either interface.

            Cow bossie = new Cow("Bossie", 12);

            // Call both IMoo and IMakeMilk methods
            bossie.Moo();                        // IMoo.Moo
            double numGallons = bossie.Milk();   // IMakeMilk.Milk

We can also set interface variables of either interface type to refer to an instance of a Cow.

            IMoo mooStuff = bossie;
            IMakeMilk milkStuff = bossie;

            mooStuff.Moo();
            numGallons = milkStuff.Milk();

#439 – Use Visual Studio to Implement an Interface

You can use smart tags in Visual Studio to quickly implement an interface for a class.

For example, let’s say that you want to add code to the Cow class to implement the IMoo interface.  You start by updating the class declaration to derive from IMoo.

If you now hover over the little underline under IMoo, you’ll see a smart tag.

If you click on the smart tag, you’ll see two options.

Click on “Implement interface ‘iMoo’ “.  Empty implementations of all of the interface’s members will be automatically added to the class.  (Note that the methods throw NotImplementedException exceptions by default).

 

#438 – Benefits of Using Interfaces

You might wonder why you’d define an interface, have a class implement that interface and then access the class through the interface instead of just using the class directly.

One benefit of interfaces is that it allows you to treat different types of objects in the same way, provided that they implement a common interface.

For example, assume that we have Dog, Seal and DrillSergeant classes, all of which implement the IBark interface (which contains a Bark method).  We can now store a collection of instances of these classes and ask all objects in our collection to Bark by using the IBark interface.

            Dog kirby = new Dog("Kirby", 12);
            Seal sparky = new Seal("Sparky");
            DrillSergeant sarge = new DrillSergeant("Sgt. Hartman", "Tough as nails");

            List<IBark> critters = new List<IBark>() { kirby, sparky, sarge };

            // Tell everyone to bark
            foreach (IBark barkingCritter in critters)
            {
                barkingCritter.Bark();
            }