Skip to content
Lesson 11 of 12

Step 1 of 7 · Reading · ~3 min

Learn

Inheritance, Interfaces, and Exceptions

Interfaces

By the end of this lesson you can declare a contract with an interface, implement it in several unrelated classes, and write code that works on any of them through the interface type.

An interface lists members a type must provide, with no code behind them. Any class that says it implements the interface must supply every member. Code that only knows the interface can then work with all of those classes without knowing which one it has.

interface IPlayable {
    string Title { get; }      // a property: implementers must provide a getter
    string Play();             // a method with no body
}

class Song : IPlayable {
    public string Title { get; private set; }
    public Song(string title) { Title = title; }
    public string Play() { return "playing " + Title; }
}

class Podcast : IPlayable {
    private int episode;
    public Podcast(int episode) { this.episode = episode; }
    public string Title { get { return "episode " + episode; } }
    public string Play() { return "streaming " + Title; }
}
  • Interface names start with I by convention (IEnumerable, IComparable).
  • Interface members are public automatically; the implementing members must be declared public too. Leave the keyword off and you get a compile error saying the class does not implement the member.
  • An implementer may add more than the interface demands (private set, extra methods), and a property can be computed instead of stored, as Podcast.Title shows.

Programming to the interface

The variable type decides what you can call; the object decides what runs:

List<IPlayable> queue = new List<IPlayable>();
queue.Add(new Song("Blue"));
queue.Add(new Podcast(12));

foreach (IPlayable item in queue) {
    Console.WriteLine(item.Play());    // playing Blue, then streaming episode 12
}

Song and Podcast share no base class, yet one list holds both. This is what interfaces buy you that inheritance cannot: unrelated types, one contract.

Several interfaces, and asking for a capability

A class has one base class but can implement any number of interfaces, listed after the colon: class Song : IPlayable, IFavorable. When you hold an IPlayable, you can test whether the object also supports another interface with as, which gives null when it does not:

IFavorable fav = item as IFavorable;
if (fav != null) {
    fav.Liked = true;
}

Interface or abstract class?

  • Interface: a pure contract, no fields or constructors, and a class may implement many. Choose it to describe what something can do.
  • Abstract class: a partial implementation with shared state and code, single inheritance. Choose it when children share real code.

Newer C# can put method bodies in interfaces ("default interface methods"), but the compiler on this course's grader predates that, so declare members without bodies. A class can also implement a member explicitly (string IPlayable.Play()), which hides it unless you go through the interface type; you will meet it mostly when two interfaces demand the same member name.

Common mistakes

  • Leaving public off an implementing member. Interface members are public, so the implementation must be too.
  • Forgetting a member. The class does not compile until it provides every one.
  • Declaring the variable with the concrete type. List<Song> cannot hold a Podcast; List<IPlayable> can.
  • Calling a member the interface does not declare. Through an IPlayable variable you see only Title and Play, not Song's extras.

Your exercise

You declare the interface and write two classes that implement it; the starter reads the input and leaves the construction and the loop to you. Hold the discounts in a list typed as the interface and apply them through it. The most likely mistake is forgetting public on the implementing members.

Up nextExceptionsInheritance, Interfaces, and Exceptions

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…