Start course
Difficulty
Intermediate
Duration
18m
Students
123
Ratings
4/5
Description

C# is a single inheritance language, meaning a class can only have one direct parent. Often single inheritance can be a limiting factor or obstacle when designing an application's class hierarchy. This course explores how C# interfaces mimick multiple inheritance, enabling a class to take on the properties and methods of other unrelated classes.

Intended Audience

This course is intended for anyone who wants to take their C# object-oriented programming to the next level..

Prerequisites

To get the most out of this course, you should have a basic understanding of C# classes. If you are unfamiliar with C# classes, please take our Introduction to object orientation and C# Class course first.

Resources

The source code used in this course is available at https://github.com/cloudacademy/csharp-interfaces.

Transcript

Let’s look at an application for modeling different transport modes around a city. We want to compare metrics like energy consumed, average speed, and CO2 emissions. From an object-oriented perspective, we need a class hierarchy that will allow us to plug any type of transport mode into a calculation to model these metrics. When I say transport modes, I’m talking about the whole range from walking, jogging, and cycling through to buses, trains, ferries, everything in between, and all combinations. 

Say we’ve got a class called Trip, with distance and elevation properties. It also has methods for calculating elapsed trip time, energy consumed, and CO2 emissions. We want to plug a transport mode object into a trip and perform the calculations. 

To do that, we need a base transport mode class from which all possible forms of transport are derived. Immediately we start to run into problems when we think of a trip involving multiple transport modes like a person walking and a person catching a bus. Unless you live in the transformers’ universe, a bus and a walker can’t easily belong to the same class hierarchy. If that wasn’t bad enough, things get complicated when considering hybrid modes like e-bikes and hybrid cars. I’ll use a transport mode interface instead of a class. All modes have a weight, drag coefficient, and average speed.

The calculate elapsed time method accesses specific properties and methods of the transport mode object to perform the calculation. We don’t care what the ancestry of the transport mode object is, just that it has the required properties and methods to support the calculation. An interface says a class that implements me implements all my properties and methods. When a method takes an interface as a parameter, or a property as an interface type, it’s saying, “I don’t care who you are; I just want to know what you do.” There are many different types of transport modes with properties and methods that are not declared in the ITransportMode interface. When accessing those classes you will not be able to access non-ITransportMode properties and methods unless you cast the ITransportMode object into the class in question.

Interfaces can be derived from other interfaces. I’ll create an ice vehicle, as in internal combustion engine, interface from ITransportMode, adding CO2 and KmPerLitre properties. Next, I’ll create a PetrolCar class that implements the IIceVehicle properties, and those inherited from ITransportMode. Not that it’s important to the demo, but the average speed is in meters per hour, so 50 kph becomes 50000. I’ll give the car a weight of 1400 kilograms. I’m not going to get into CO2 emissions, so I’ll get the CO2Emissions default method to return 0. Now that we’ve created the PetrolCar class, which implements ITransportMode, let’s try accessing KmPerLitre through TransportMode. As I said earlier, KmPerLitre isn’t recognized until I cast TransportMode as a PetrolCar class by putting the class type in brackets in front of TransportMode. This is something to remember when designing your interfaces and classes.

I’ll move the EnergyConsumed calculation from the trip class to ITransportMode and get the mode to calculate it based on elevation and distance, and return the result to the trip. The calculation approximates pushing a weight up a frictionless slope a particular distance but is irrelevant for the purpose of this demonstration. I’ll do the same for CO2Emitted.

A human has weight,  basal metabolic rate, and average speed, which will affect calories consumed depending on the trip route. The human energy consumed method is different from that of ITransportMode from which it is derived, hence the squiggly line. C# sees a conflict between the EnergyConsumed method in the ITransportMode parent and this one in IHuman. A derived interface can kind of override a method of an ancestor interface. However, it’s more reimplementing than overriding, as we reference the original interface in the child interface’s method signature but change the code.

Next, I’ll create a class called HumanPower that implements the IHuman interface. From HumanPower, we derive walker, runner, and cyclist. We’ll need an electric vehicle interface descended from ITransportMode, and from that, we can create an e-bike class derived from the human cyclist class and also implements IElectricVehicle.

Now we can use the classes to do some very basic calculations. First is a trip of 1500 meters with an elevation of 65 meters made by a walker with a basal metabolic rate of 1750. We can get the elapsed time of the walk and how much energy was consumed. The next trip is 4.5km with an elevation of 225 meters in a car. Before we run this, let’s override the ToString method in the trip class to print out a trip summary. We’ll print the transport mode using the GetType method in conjunction with ToString, followed by the distance in meters and elevation expressed as a gradient percent. Then we’ll print out the trip time and the energy consumed. I’ll add the console write line statements for each trip and run the program. Great, it works, and the elapsed times seem about right, but we don’t know what the energy consumed numbers mean.

 

I’ll create an Enum EnergyType with Unknown, Calorie, and NewtonMeter elements and add a read-only EnergyMeasure property in ITransportMode. We need to add this property to the classes implementing the ITransportMode interface. For HumanPower, EnergyMeasure will return calorie, and PetrolCar will return NewtonMeter. We can add TransportMode EnergyMeasure.ToString to the end of the trip ToString output. Running the program again gives us the correct result in terms of the correct code being executed. Obviously, the calculations and physics involved are dubious, to say the least, but a good example of using interfaces to execute dynamic code with not an if-statement in sight.

About the Author
Students
21181
Courses
72
Learning Paths
14

Hallam is a software architect with over 20 years experience across a wide range of industries. He began his software career as a  Delphi/Interbase disciple but changed his allegiance to Microsoft with its deep and broad ecosystem. While Hallam has designed and crafted custom software utilizing web, mobile and desktop technologies, good quality reliable data is the key to a successful solution. The challenge of quickly turning data into useful information for digestion by humans and machines has led Hallam to specialize in database design and process automation. Showing customers how leverage new technology to change and improve their business processes is one of the key drivers keeping Hallam coming back to the keyboard. 

Covered Topics