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
Iby convention (IEnumerable,IComparable). - Interface members are public automatically; the implementing members must be declared
publictoo. 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, asPodcast.Titleshows.
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
publicoff 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 aPodcast;List<IPlayable>can. - Calling a member the interface does not declare. Through an
IPlayablevariable you see onlyTitleandPlay, notSong'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.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…