Strictly speaking, declaring an interface is a waste of time. You could skip the interface and save some time.
However, you would be cutting the wrong corner. While it's a bit of extra time and work, in the long run interfaces are invaluable. One of the marks of a truly great software engineer is being able to design interfaces well.
To be less abstract, the interface is designed for precisely that purpose: To formalize the interface between two kinds of classes (in other words, how the two classes work together). It is a bit like a contract between classes, where each class says what they promise to provide and what they will expect. Your IVehicle
example, for instance, vows that it will always have a property called doors
. Then, any code which works with IVehicle
can trust all implementations of IVehicle
to always have a Doors
. You can now safely write code which accesses IVehicle.Doors
knowing that no matter what particular implementation happens to get passed to this method, your code will definitely work - even if the Vehicles
package developer decides to one day add some vehicles you've never heard about or considered!
When you have only one small class implementing the interface, and you are the only developer, interfaces may be superfluous. However, what if there were multiple kinds of vehicles, each with their own logic and different members, which must nevertheless be used by some general code? For example, a vehicle tracking manager must handle classes Car
, Truck
, Plane
and so on. Why not? They all have a speed and position, and that's all that matters.
Moreover, when you let other developers write their own vehicles, the interface is a great way of showing them how they must do this for it to work with the rest of your code.
Likewise, when you work on a large project, and split each part between different developers, well-designed interfaces can ensure that these programmers, working on different parts of the project in relative isolation, will still create a whole which works thanks to parts that fit together nicely.
Similarly, a good interface is a great way to start a complicated class even when coding on your own: It will help you keep track of what you need to implement and how, but unlike a more familiar technical specification, an interface can be understood by the compiler so that it can assist you in many ways (such as help from IntelliSense when you want to write logic using parts of your class that you will implement later).
In C# particularly, interfaces also have a practical benefit. You can't inherit from more than one class or abstract class in C# (unlike C++). This is done because multiple inheritance turns out to make life very difficult for programmers sometimes. But you can inherit from multiple interfaces, and because they are only interfaces (with no implementation) the "multiple inheritance" thing is much less of an issue.
Lastly, a real world example: Microsoft has provided for you a List.Sort
method which will helpfully sort a list of any object. It is obviously easy to do this for things like numbers and strings, but it is possible to make it sort arbitrary objects you made, like vehicles. But how could Microsoft possibly know what kinds of classes you will implement, and how you intend for these to be sorted? They don't, but they provide for you an interface called IComparable
. This defines the methods that sorting code needs to call to be able to compare two objects for sorting. If the object you put into your list implements this IComparable
, you will have told Microsoft's List.Sort
code how your objects should be sorted, and now you no longer have to write your own sort function since you can just use the well designed, tested, documented and debugged Microsoft one.
As an exercise, try writing a program which takes a list of Triangle
classes (which have only a
, b
, c
fields that store the length of each side, and a CalculateArea
method) and then sorts it by area using Microsoft's List.Sort
. Don't write your own sorting code, and don't use thing like LINQ OrderBy
, instead do it by making Triangle
implement IComparable
. Then think about this: If you were the project manager in charge of development of all the .NET libraries, how would you write a sort function that anyone can use, even with their own weird classes?