Lecture thumbnail 0:00 / 0:00 The next principle that we’re going to consider is the Liskov substitution principle named after Barbara

Liskov.

So the idea here is quite simple.

The idea is that you should be able to substitute a base type for a subtype.

And once again, I know this sounds really cryptic and you might not be understanding what’s going on.

So let me explain and I’m going to explain.

Using the classic demonstration of the Liskov substitution principle by using an example with just a

bunch of rectangles and squares.

And that’s an interesting, object oriented challenge, by the way.

So let’s suppose that we have a class called Rectangle and we’re going to define both the width and

the height.

So to begin with, I’m just going to have them as automatic properties.

So I’ll have the property called width and similarly another property called height.

There we go.

So now that I have this rectangle, I can make an empty constructor, I can make a constructor which

initializes each of the properties.

And in addition, let’s build some sort of two string implementation where we can output the information

about this particular object.

So I’ll make some formatting members just a two string which will tell us what the rectangle is all

about.

So this is a fairly straightforward object to use and you can go ahead and use it in main, you can

say rectangle RC equals new rectangle like so.

And then we might want to perform some action on a rectangle, like for example, calculating the area

of this rectangle.

So to calculate the area I can say static public int area which takes a rectangle R and it returns r

dot width multiplied by r dot height, as simple as that.

And what we can do now is we can output not just some information about the rectangle, but also calculate

the area.

So for example, what I can do here is I can write line.

I can write line that I have the rectangle, which is RC in our case, and I can say rectangle has area

and then I can calculate the area using the area function that we’ve just made.

So I call area RC here and we can execute this and just take a look at the result to see that it’s all

actually working.

So here is the output we have with zero height, zero has area zero, not very exciting.

So I’ll put some numbers here, like two and three for example, and we can go again and this time two

times three equals six.

So everything is great.

Okay, now this is fine until you decide to also implement a square class and you decide to inherit

square from rectangle because why not?

So here is square, which geometrically is in fact a kind of rectangle.

So we say square is a rectangle and then we need to decide how to handle the assignments to the width

and the height.

Because remember, the square has to be consistent, be a square.

You cannot turn it into a rectangle all of a sudden, or you could do it.

But that’s not what we’re going to do.

Instead, we’re going to define new width and height setters.

So suppose you go ahead and you write something like this public new int width and you specify a new

setter where when somebody changes the width, they change the height as well.

You can see this going wrong already, can’t you?

Okay, so based on width equals base dot height equals value.

Terrible idea.

And then the same goes for the height public new int height where we set the base dot width equals base

dot height equals value like so.

So this might seem workable in principle and we can actually start using it and getting correct results,

surprisingly enough.

So for example, if we say we make another rectangle or let’s say we make a square now, so square square

equals new square and we’ll set the square width.

So squat width, we’ll set it to a value of four.

So we expect the area to be 16 if we write line this.

So write line SQ has area and we consider using the area function once again.

So we call the area function with SQ this time around.

And if I execute this, you can see that we have correct operation.

Everything is fine.

Everything is absolutely fine.

Why are we even discussing this strange substitution principle?

Well, the reason for this is that if you have a square, then it is perfectly legal for you to store

a reference to a square as a rectangle variable.

Because remember, inheritance, basically a square is a rectangle.

So I should be able to legally change this to a rectangle and nothing should change, right?

Well, wrong.

We now have a height of zero and an area of zero.

Now I’m sure you can guess why this happened.

This happened because when you setting the width, you are only setting the width.

That’s it.

You are not setting the height or anything.

So the liskov substitution principle basically says that you should always be able to sort of upcast

to your base type and the operation should still be generally okay, meaning that the square should

still behave as a square even when you are getting a reference to a rectangle for it.

So the question is, well, how do we fix this violation of the liskov substitution principle?

And the fix is actually rather easy.

All you have to do is you have to make sure that if there is in fact an override of width and height,

it is indicated as such, because what we’ve done here is we’ve used the new keyword, but instead what

we can do is we could do something better, we could make the properties virtual so we could go up here

and make each of the properties virtual like so.

And then of course, instead of new, you would put override and override here as well.

So this time around, if we actually execute this, let me just show you that it’s now working correctly.

Again, what happens is even though you’re holding a rectangle reference to a square, when you go and

access the width, what really happens is a walk over the virtual function table because it’s looking

at width, but it’s saying, Oh, okay, let’s look at the setter.

Oh, the setter is virtual.

So how about we look at the V table?

And so it finds the appropriate setter and calls the appropriate setter, in fact, on the square.

So this is the liskov substitution principle.

Play Play Play Stop Play Play Play