Interfaces
The fleet needs someone to carry cargo. The job ad has one requirement: "can carry cargo and says how many kilograms it will take." A truck fits, and so does a porter with a hand cart. The ad does not care who you are or where you come from: what matters is that you can do what it lists.
A base class cannot describe such a requirement. A derived class is a kind of its base class, and a porter is not a kind of vehicle. Besides, a class has only one base class: if it already has one, you cannot add a second.
For requirements like this, C# has the interface: a list of members that a class promises to have. A class that keeps this promise implements the interface:
ICargo[] carriers = [new Truck(), new Porter()];
foreach (ICargo c in carriers)
{
Console.WriteLine(c.MaxLoad()); // 5000
// 50
}
interface ICargo
{
int MaxLoad();
}
class Truck : ICargo { public int MaxLoad() => 5000; }
class Porter : ICargo { public int MaxLoad() => 50; }Let's walk through it line by line:
interface ICargodeclares an interface with one method,MaxLoad. The method has no body: the interface says the method exists, but not how it works. By convention, interface names in C# start with the letterI.class Truck : ICargoimplements the interface: the class must have a methodMaxLoadwith the same return type and the same parameters, declaredpublic.Porterhas nothing in common withTruckexcept the interface, and it implements the interface in its own way.ICargo[] carriersis an array of an interface type: it holds references to objects of any classes that implementICargo.c.MaxLoad()runs the object's version:5000for the truck and50for the porter.
A contract the compiler checks
An interface is a contract, and the compiler checks that the class has met each of its terms. Suppose ICargo also has a method int MaxDistance();, and Porter does not declare it. Then the program does not compile:
error CS0535: 'Porter' does not implement interface member 'ICargo.MaxDistance()'You cannot create an object of an interface: the line new ICargo() gives the error CS0144. But a variable of an interface type can lead to an object of any class that implements the interface.
Here the job ad analogy is off. A hired worker does everything they can, even beyond the ad. But through a variable of type ICargo, only the members of the interface itself are visible, even if the class has others.
Several interfaces
One worker can fit several job ads at once. A class can also implement several interfaces: you list them separated by commas.
var drone = new Drone();
Console.WriteLine(drone.MaxLoad()); // 5
Console.WriteLine(drone.Battery()); // 70
interface IElectric
{
int Battery();
}
class Drone : ICargo, IElectric
{
public int MaxLoad() => 5;
public int Battery() => 70;
}This fragment continues the first program. A drone carries cargo and runs on a battery, so it implements both interfaces and declares the methods of both.
A class has only one base class, but it can have any number of interfaces. When a class has both, the base class comes first in the list: class ElectricVan : Vehicle, ICargo, IElectric. In any other order, the compiler gives the error CS1722.
Interviewers often put it this way: "Does C# have multiple inheritance?" The answer has two parts:
- you cannot inherit from several classes: a class has one base class;
- you can implement several interfaces, and that is how one class fits several roles.
Abstract class or interface
This is another classic interview question. Both an abstract class and an interface describe what the classes that inherit from them or implement them must be able to do, but they are built differently:
| Abstract class | Interface | |
|---|---|---|
| How many a class can have | one, as its base class | any number |
| Instance fields and constructors | allowed | not allowed |
| What it unites | related classes with shared data and code | any classes with a shared ability |
Since C# 8, an interface method can have a body, called a default implementation. But an interface still has no instance fields and no constructors. So shared data lives in an abstract class, while an interface describes an ability.
Common mistake
A method of the interface was implemented, but public was forgotten:
ICargo cart = new Cart();
Console.WriteLine(cart.MaxLoad());
interface ICargo
{
int MaxLoad();
}
class Cart : ICargo
{
int MaxLoad() => 100; // ✗
}error CS0737: 'Cart' does not implement interface member 'ICargo.MaxLoad()'. 'Cart.MaxLoad()' cannot implement an interface member because it is not public.The program does not compile. Class members are private by default, while a member that implements an interface must be reachable by any code that works through that interface. In the interface itself, public is not written: its members are public by default. In the class, the word is required: public int MaxLoad() => 100;.
Key points
- An interface lists members that a class promises to have; a class implements it by declaring each of them
public. - A class can implement several interfaces, but it has one base class.
- A variable of an interface type leads to an object of any class that implements the interface.
- An abstract class can have instance fields and constructors, and an interface cannot.