In a previous session Getting Started with C# Interfaces, I talked about how you can use C# Interfaces to drive consistency across different C# Classes. In this session, I’m going to walk through one of the cool features of Interfaces, which is Polymorphic Behavior.
Polymorphism is not only a big word you can impress friends and family with, it’s actually really useful for what I call future-proofing your apps.
Let me show you an example. We currently have a car and a lawn mower and both of those implement “IMachine”, which simply has a start and a stop method.
Both of them have to have those two methods or it won’t compile. We’ve already shown that earlier in a previous session Getting Started with C# Interfaces.
[0:42] What I’m going to do now is, let’s assume that this is our big program here.
I want to add a particular method into this program that actually handles starting or maybe even stopping the car or the lawn mower. But I don’t want to hard-code that it only handles a car or a lawn mower.
[1:00] Let me show you what I mean. Let’s say that I had a static void start and it took a car.
I could obviously do some logging, so we’ll pretend that our app does a little bit of logging. Then we could call “car.start,” and we’d be off and running.
That’ll work, and I could come in then and we could kind of cut and paste this. We could change this to a lawnmower. I’ll just change this to “m,” for “mower,” and we could say “m.Start.”
There’s nothing wrong with that. I now have an overload, and it would work, but now it would have to know which of these two to actually call.
[1:43] To demonstrate Polymorphic Behavior, we’re going to leverage the Interface, and what I’m going to do is allow someone to pass in an IMachine.
Now, we’ll just call this “machine.” What the machine can do now is we know if it implements this Interface it has a start, or stop because, otherwise, it wouldn’t have compiled in the first place.
[2:06] We’ll go ahead and change this to “machine.start.” Imagine that we did some logging and then we’re going to start it. Now, what can it start? The answer is anything that implements IMachine.
When I first learned this I thought this was useless because you can’t create an instance of an Interface. As I showed earlier, an Interface has no implementation.
Therefore, you can’t “new” it up or use it in any really useful way. You can just implement it, that’s it.
[2:37] The first time I saw this I said, “That’s useless code. Why would you ever do that?” The answer is I’m not saying “Pass me an IMachine.” I’m saying, “Pass me anything that implements IMachine.” We know that car implements IMachine and we know that lawnmower implements IMachine, therefore they are candidates to pass in.
Let’s come on down, we’ll do a new class and we’ll just call it “truck.”
In the truck, we could also have some type of methods. I’m not going to be able to pass, obviously, a truck into the start because it doesn’t implement IMachine. Of course, if I make it implement IMachine, and then implement the members, it would work.
[3:22] Let’s assume that we just have car and lawnmower. Now what we can do is, let’s take out this extra line.
Now I’m going to call start and pass in the car. We’ll call start again and pass in the mower.
This is a console app, so I’m just going to do a console read real quick so it stays up.
[3:43] Now let’s run and see what kind of output we get and you’ll notice it worked. We got car started and lawnmower started.
That is Polymorphic Behavior, so let’s define that a little more specifically.
Polymorphism ‑‑ if you’re not familiar with the term ‑‑ is when an object implements a particular set of behaviors, such as start and stop. But the way it performs between the objects, the start or the stop is different.
A simple example I like to give in the classroom scenario is, animals speak. A dog speaks, a cat speaks, but the way they speak is different. A cat meows, a dog barks, a monkey…I don’t know…ooh, ooh, ah, ahs, or something like that.
[4:25] In the case of a car and a mower, they both start, but the way they start is going to be different. Obviously, it’s different because I typed some text. In real life, it’s very different because, in a car, you’re obviously turning a key, or maybe pushing a button whereas in a lawnmower, you’re probably pulling a string, or something like that. Unless it’s a riding lawnmower, I suppose.
This now illustrates how we can future-proof our app. Let me prove it by adding one more class into the mix.
Let’s say that we also add an Airplane.cs.
[4:59] To be consistent, I’ll make this public and I’ll implement IMachine, because an airplane would have a start and a stop.
Then we’ll just do the same type of thing here. We’ll say airplane started and we’ll return whatever we want, in this case “true“.
We’ll also make a console right line that airplane stops.
[5:41] Assuming that this had real code in it that actually does something useful, now, without ever changing this method, I can pass in an airplane. Because airplane implements IMachine and so, now, I come in and say, “VARAIR=new airplane.”
Now we can call start. You’ll see an Intellisence, it says “pass me an IMachine.”
We can go ahead and pass it the air, for the airplane.
[6:09] You’ll really see Polymorphism because we have three things that all start, but the way they start is different. The car writes car, lawnmower or airplane, as you see here.
That is a really powerful feature in programming. Because if you have methods in your code, like start that need to be able to accept different parameters, and you want to future-proof it, because you might not know all the objects that might be passed in the future to this method.
[6:35] Then, by implementing an Interface, I’m now writing very loosely coupled code, we call it because I can swap things in and out, and not have to rewrite this entire method. In fact, this method doesn’t even know what it’s doing. It just knows that I can call “start,” and whatever object you pass in, then it will invoke the start on that particular object.
That’s a quick and simple example of getting started with C# Interfaces and Polymorphic Behavior. I hope it helps you kind of rethink through how you architect your apps and how you can do some future proofing of some of your different methods in other Classes.
Next we’ll look at using C# Generics in your applications.