#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; }
    }


Advertisement

#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();
            }


#437 – Access Interface Members through an Interface Variable

Once a class implements a particular interface, you can interact with the members of the interface through any instance of that class.

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

            // Cow implements IMoo, which includes Moo method
            bossie.Moo();

You can also declare a variable whose type is an interface, assign it to an instance of any class that implements that interface and then interact with members of the interface through that interface variable.

            // bossie is a Cow, which implements IMoo, so we can point IMoo variable at her
            IMoo mooer = bossie;
            mooer.Moo();

In either case, we end up calling the same Moo method.

Notice that we can’t access members of Cow that aren’t part of IMoo using this interface variable.

Even though MakeSomeMilk is a public method in the Cow class, we can’t access it via IMoo.

#436 – The Implementation of an Interface Can Be a Subset of the Class

When a class implements an interface, it is declaring that it implements all members of the interface.  Client code can interact with an instance of the class through the members of the interface.  It can also interact with class members that are not part of the interface.

For example, assume that the Cow class implements the IMoo interface, which contains the Moo method.  Client code can invoke the Moo method on instances of the Cow class, since it implements IMoo.

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

            // Invoke IMoo.Moo
            bossie.Moo();

Clients can also call methods that are not part of the IMoo interface.

            // Call methods and set properties that are NOT part of IMoo
            bossie.MakeSomeMilk();
            bossie.Motto = "Docile but still a maverick";

#435 – Implementing an Interface

An interface is a list of class members that a class must implement if it chooses to implement the interface.

Assumed that we have the following IMoo interface.

    interface IMoo
    {
        // Methods
        void Moo();

        // Properties
        List<string> MooLog { get; set; }

        // Events
        event EventHandler<MooEventArgs> CowMooed;
    }

A class implements an interface by first listing the interface in the class declaration, as if it was inheriting from the interface.  It then provides implementations for all of the interface’s members.

    public class Cow : IMoo
    {
        //-- IMoo implementation --
        public void Moo()
        {
            string moo = "Moo !";
            Console.WriteLine("{0}: {1}", CowName, moo);
            MooLog.Add(moo);
            OnCowMooed(moo);
        }

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

        public event EventHandler<MooEventArgs> CowMooed = delegate { };

        protected virtual void OnCowMooed(string mooPhrase)
        {
            CowMooed(this, new MooEventArgs(CowName, mooPhrase));
        }
        //-- IMoo implementation --

        public string CowName { get; set; }
    }