#612 – Members of an Interface Are Implicitly Public

The idea of an interface is to define a contract that a class can choose to implement.  Since an interface is a public definition of a contract, it doesn’t make sense for members of an interface to be private.  This means that all members in an interface are implicitly public.

    public interface IDogStuff
    {
        // Implicitly public
        bool CanBark { get; set; }
        void Bark();

        // Compile-time Error: The modifier 'public' is not valid for this item
        public void Fetch();

        // Compile-time Error: The modifier 'private' is not valid for this item
        private void PeeOnTree();
    }
Advertisements

#601 – A Class Can Both Inherit from A Parent Class and Implement an Interface

Every user-defined class inherits from exactly one other class.  You can either explicitly specify the class to inherit from, or the class can implicitly inherit from System.Object.

A user-defined class may optionally implement one or more interfaces.

A class may therefore both inherit from a parent class and also implement one or more interfaces.  All of the declarations listed below are valid class declarations.  (Class members are not shown).

// Implicitly inherits from System.Object
public class Movie
{
}

// Explicitly inherit from a class
public class Terrier : Dog
{
}

// Implement one or more interfaces
public class Dog : IBark, IFetch
{
}

// Inherit and implement an interface
public class BorderCollie : Dog, IHerd, IObsess
{
}

#537 – Implement a Generic Interface with a Generic Class

When a class makes use of a generic interface, it can choose to implement the constructed interface, supplying all type parameters for the interface.

public class Farmer : IRememberMostRecent<Joke>

A class can also implement a generic interface, as long as the class itself is generic. Type parameters for the interface are supplied to the class when it is constructed.

    public class Dog<T> : ICanEat<T>

This type parameter (or parameters) can then be used in instance methods that implement the interface.

        // ICanEat.Eat
        public void Eat(T thingToEat)
        {
            // ...
        }

You can also use the type parameter passed to the class in instance methods that are not part of the interface.

        // Not part of the interface
        public void PlayWith(T thingToPlayWith)
        {
            // ...
        }

#536 – Using a Generic Interface

Like classes, interfaces can be generic.  Below is an example of a generic interface with  a single type parameter.

    public interface IRememberMostRecent<T>
    {
        void Remember(T thingToRemember);
        T TellMeMostRecent();
        List<T> PastThings { get; }
    }

When a class implements this interface, it can choose to fully construct the interface (provide a type).

    public class Farmer : IRememberMostRecent<Joke>
    {
        public string Name { get; protected set;  }

        public Farmer(string name)
        {
            Name = name;
            lastJoke = null;
            allJokes = new List<Joke>();
        }

        // IRememberMostRecent implementation
        private Joke lastJoke;
        private List<Joke> allJokes;

        public void Remember(Joke jokeToRemember)
        {
            if (lastJoke != null)
                allJokes.Add(lastJoke);

            lastJoke = jokeToRemember;
        }

        public Joke TellMeMostRecent()
        {
            return lastJoke;
        }

        public List<Joke> PastThings
        {
            get { return allJokes; }
        }
    }

Using the Farmer class:

            Farmer burton = new Farmer("Burton");
            burton.Remember(new Joke("A man walks into a bar.", "Ouch"));
            burton.TellMeMostRecent().Output();

            burton.Remember(new Joke("What's red and invisible?", "No tomatoes"));
            burton.TellMeMostRecent().Output();

#456 – Explicitly Implemented Interface Members Are Automatically Private

When you explicitly implement an interface member in a class, you make the member accessible only through objects whose type is the interface and not through objects whose type is the class.

    public class Cow : IMoo
    {
        void IMoo.Moo()
        {
            Console.WriteLine(string.Format("{0} says Moo", Name));
        }

        // rest of class here
            Cow bessie = new Cow("Bessie", 5);

            // bessie.Moo();    // Compile-time error

            IMoo viaMoo = bessie;
            viaMoo.Moo();       // OK

Because explicitly implemented interface members are not accessible via normal class instances, all explicitly implemented members are implicitly private.  These members cannot include an access modifier (either private or public).

#455 – Define an Interface Based on Existing Members of a Class

You can use Visual Studio to define a new interface, based on existing members of a class.  This is also known as extracting an interface.

For example, suppose we have an existing Cow class that doesn’t currently implement any interfaces.  A Cow has properties like Name, MooLog and Motto, and methods like Moo, Dance and Burp.

We can create a new IMoo interface that consists of a Moo method and a MooLog property.  Since Cow already implements both of these members, we can extract the interface from the class.

Right-click on the Cow class name and select Refactor and then Extract Interface.

We then give the new interface a name (e.g. IMoo) and select the members of the existing class that should be part of the interface.

After clicking OK, Visual Studio generates the new interface.

Cow now inherits from IMoo.

#454 – Return an Interface as a Return Value from a Method

In addition to passing interface variables into a method as parameters, you can also pass an interface back as the return value of a method.

In the example below, we define a method that looks through an array of objects and returns the first object found that implements the IMoo interface.

        static IMoo FindAMooer(object[] candidates)
        {
            IMoo theMooer = null;

            foreach (object candidate in candidates)
            {
                if (candidate is IMoo)
                {
                    theMooer = (IMoo)candidate;
                    break;    // stop looking
                }
            }

            return theMooer;
        }

We can then pass in any array of objects to this method and the method will find the first one that can moo.

            Cow bessie = new Cow("Bessie", 4);
            Dog spike = new Dog("Spike", 5);

            IMoo mooer = FindAMooer(new object[] { spike, 42, "Jude", bessie });
            mooer.Moo();