Interfaces
The Crash Course
- An interface, in general terms, is the things that something provides for the outside world to use.
- C# has an interface concept that works very much like a class, specifically a pure abstract base class—that is, an interface is a set of methods or properties that any class that uses or "implements" the interface must provide.
- To create an interface, you simply use the interface keyword where you would previously have used the class keyword.
- Methods and properties of an interface do not need to be declared abstract or public because both are assumed to be the case (and required).
- To make a class use an interface, you list the class in the same way as you would a base class: class ImplementingClass : Interface { /* put the interface's methods here, as public methods */ }
- You can implement multiple interfaces or derive from a single base class and implement any number of interfaces, but you cannot derive from multiple base classes.
Introduction
In this final tutorial about object-oriented programming, we'll discuss interfaces in C#. An interface is very similar to the abstract base classes we saw in the previous tutorial. We'll start off with a discussion of what an interface is and look at how to actually create an interface. We'll finish up with a brief discussion about multiple inheritance, why C# doesn't support it, and how interfaces allow us to get most of the same effect.
What is an Interface?
At a conceptual level, an interface is basically just the kinds of things an object presents to the outside world to interact with it. Your TV, for instance, probably has several buttons on it (and if it is really old, maybe even a dial or two). Each of these things allows the outside world to interact with it. The object's interface is its contract to the world that it can do certain things. (This is why it is frustrating when an elevator has a "Close Door" button, but it doesn't actually work. It should work, gosh darn it! There's a button for it and everything!)
C# has a construct built into it called an interface that does this same thing, listing a set of methods that a class that uses the interface is committed to providing.
Interfaces are very similar to the abstract base classes we already looked at. In fact, imagine you had an abstract base class, where every single one of the methods it created was abstract (provided no implementation), and the class had no instance variables or properties. You've basically got an interface! (In C++, this is called a "pure abstract base class"—they have no built-in interface construct.)
Creating an Interface
Creating an interface is actually very similar to creating a class. As an example, let's say our program has a need to write out files (something we'll discuss more in the next tutorial, actually), but you want to be able to write to lots of different file formats. We can create different classes for all of the different kinds of file writers we have (one for each type of file we want to). But they are all going to do basically the same thing, at least as far as the calling code is concerned. They'll all have the same interface.
To model this, we can create an interface in C# for file writers:
public interface IFileWriter { string Extension { get; } void Write(string filename); }
This is very similar to a class, with a couple of small differences. One, we use the interface keyword instead of the class keyword.
Two, as you can see, all of our methods and interfaces look like the abstract methods we talked about in the last tutorial, and they don't have a method body. But notice that we also don't have to say virtual. Nor do we say that it is public (or private or protected for that matter). Since this is an interface, we already know that the methods are going to be left unimplemented, and we also know that the methods must be public.
(Modern C# allows you to put public on interface members, but it is not required and isn't usually done.)
Three, this interface name starts with a capital I. This is not required but is a C# idiom that is nearly universally applied. It is one of those "When in Rome, do as the Romans do" things. Try it for a while, and if you still hate it after a few months, you can ditch the I.
Now, we can go ahead and create classes that use this interface.
So we might have a text file writer:
public class TextFileWriter : IFileWriter { public string Extension { get { return ".txt"; } } public void Write(string filename) { // Do your file writing here... } }
This class is said to implement the IFileWriter interface. It uses the same notation as deriving from a base class.
To complete the job, the class must have a definition for all members listed in the interface. These must be public, but you do not put override on them since it is not overriding anything.
However, the class is allowed to add more members beyond the interface if it needs them. The interface demands that it supports a set of features, not that it is limited to that feature set.
In most ways, an interface will work in the same way that a base class does. For instance, we can have a list of our IFileWriter interface and put different types of objects that implement the IFileWriter interface in it:
IFileWriter[] fileWriters = new IFileWriter[3]; fileWriters[0] = new TextFileWriter(); fileWriters[1] = new RtfFileWriter(); // we haven't implemented this type anywhere, yet fileWriters[2] = new DocxFileWriter(); // we haven't implemented this type anywhere, either foreach (IFileWriter fileWriter in fileWriters) { fileWriter.Write("path/to/file" + fileWriter.Extension); }
Multiple Inheritance and Why C# Doesn't Support It
In some programming languages, you have the ability to create a class that is derived from multiple base classes. Say, for instance, you have a Person class, which provides things like a name and age, and a NoiseMaker class, which has a method called MakeNoise(). But then you have a Musician class, which is both a person and a noise maker. Your first reaction might be to make the class have both Person and NoiseMaker as base classes.
Doing this is called multiple inheritance, but C# doesn't allow it. You have to choose only one to derive from.
C# opted not to support this because of the complexities that arise when you have it. In particular, when two base classes derive from yet another class, it is unclear which flavor of overridden methods should be used in different circumstances. To sidestep this confusing area of programming, the language designers opted to just… avoid it.
On the bright side, C# allows you to implement as many interfaces as you want. So one potential workaround to multiple inheritance is to express one or all of the things that would have been base classes as interfaces instead of classes. If we had an IPerson interface and an INoiseMaker interface, the Musician class could implement both interfaces just fine.
Specifying multiple interfaces (or a base class and interfaces) is done by listing all things the class derives from, separated by commas:
public class Musician : IPerson, INoiseMaker { // ... }
Note that if you have a base class, that must come before any interfaces.
What's Next?
We've got one more topic to talk about, regarding classes. It's a cool and powerful feature called generics, which is a way to make classes that can be reused to contain any type of data we want. (It's generic!) We'll start by taking a deeper look at why we would want them, and how to use a few built-in classes that use generics, and then we'll look at how to make our own!
One small correction: the ‘What's Next?’ section misses/skips chapter 22 (‘Writing to and Reading from Files’).
You are correct. The ordering with the Previous and Next links was different than the top-level page. I've corrected it now.
Post preview:
Close preview