Liskov Substitution Principle Explained - SOLID Design Principles

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone you have really been loving my solid design principle videos so here's the third one which is going to be covering the Liskov principle which in my opinion is one of the most important principles for writing really good object-oriented code so let's get started with that right now welcome back to web dev simplified my name is Kyle and my job is to simplify the web for you so you can start building your dream project sooner so that sounds interesting make sure you subscribe to the channel for more videos just like this one and now to get started with the list cough principle I'm first going to read off the definition which is that if s is a subtype of T than objects of type T may be replaced with objects of type s and that is a mouthful of jargon that really doesn't make too much sense but essentially what this is saying is if you have an object at class let's say for example you have a class of animal every single place that you use the animal class you should be able to replace it with one of its subclasses so if you have another class called dog which inherits from animal then every single place that you use animal you should be able to use dog and it's going to work just as well as it did before that is what the list cough principle says anywhere that you use one type of class you need to be able to use all of the subclasses of that class and it should work just fine so let's jump into an example where we have two different classes we have a rectangle class and then we also have a square which extends rectangle and that is because we know that every single square is going to be a rectangle because every square is a four-sided object and a rectangle is also a four-sided object so we know every square is a rectangle but not every rectangle is a square so that's why we have the relation in this direction where a square extends rectangle and all this is is it takes a constructor which gives you the width and height and then there's a function for setting the width studying the height and then getting the area and then inside of the square we changed our set width and set height make sure you don't even need this area we changed our set width and set height so that it's always going to set both of the sides the width and the height to always be exactly same so that it's actually a square and not a rectangle hence why it's in the square class and then we created two rectangles down here we increase their width and then printed them out and this increase width function all it does is it sets the width of the rectangle to one more than what the width currently is and as you can see we have two rectangles this one right here is 10 by 20 this one's five by five and so when we increase the width from ten to eleven we get an area of twenty two which we see printed on the right and here when we increase the width from five to six we get an area of thirty which is showing over here but you may notice that this rectangle right here is actually a square so we should just change this to be a square change rectangle to to just be square here we can come and replace all of our rectangle twos with square and we should see the exact same thing happen everything is going to be the same over here right 22 and 30 because we're now calling this increased rectangle with with a square which is a subclass of rectangle so according to list coffs principle all of this should work exactly the same as before but when we run this you'll notice we get 36 here as the area of our square and that is because when our Square enters this increased width function it increases the width by one but that also increases the height by one because our width and height always are exactly the same so now it is a six by six square instead of a six by five rectangle so this function right here is breaking the loof scoff substitution principle essentially the problem is that our subclass of square is not actually compatible with every function that we're using our rectangle for our square cannot be substituted in place of a rectangle so we now are failing that Liskov substitution principle and this is sometimes a tricky problem to fix but in this example one of the easiest ways to fix this would be to change what we're inheriting from so we want to create another class this class would be for example shape and this shape class here would actually just have this area function for example so we could have an area function and it'll be implemented and it'll do some kind of code in here to return the area and then our rectangle is going to extend shape and our square is going to extend to shape so now our rectangle and our square are both extending from shape instead of extending from rectangle and now our API is going to work just fine because when we set the width for example in our rectangle it's going to modify just rectangle stuff and we would need to have for example increase shape with but obviously our shape doesn't really have a width so this doesn't really work as is but you get the point that what we need to do is we need to create an object that we can actually inherit the rest of our objects from this example is more so just to show you how the Liskov principle works and how code that may look fine this rectangle and square code we had before is actually incorrect because it's violating that Liskov substitution principle I have another example that I'm going to jump to we can show exactly another way that the Liskov substitution principle is violated and how we can actually fix it so here I have another example of the Liskov substitution principle and we have three different classes our first class is our base class which is a bird and all of our birds can fly because birds can fly so we have a v function on our bird our next class is a duck class which extends bird because it is a bird and it has a quack function because ducks quack and then lastly we have a penguin function or a penguin class which extends bird because a penguin is a bird and penguins can't fly so we're throwing an error saying hey we can't fly we can't actually do this but we also have a swim function because penguins can swim so it says I can swim and then inside of here we have a make bird fly function which just calls fly on a bird and then we're creating two different birds duck and penguin and then we're making them fly and as you can see the duck prints out I can fly just fine but the penguin is throwing an error saying it cannot fly and this is again another instance of the list cough substitution principle not working because this is a bird function so it expects a bird class and we're passing in both of the subclasses of bird duck and penguin and according to the principle every subclass of a class must be able to make this function work properly and the duck function works fine so this duck is passing the list cause substitution principle but the penguin class is because the penguin class cannot fly and thus it works differently than its parents class which can fly so we're failing the Liskov substitution principle and an easy way to fix this is to change it so that we don't just have a bird subclass we have a flying bird subclass so we're gonna say we're gonna have flying birds and our duck is going to extend from flying bird and then we're also going to create a swimming net bird and then we're going to put our swim method inside of there so let's just copy that paste that into our swimming bird and of course some type England can swim it is going to be a swim bird and we don't need to worry about this five function anymore now what we can do is we can make a flying bird fly then we can have another function which is going to make a tea swimming whoops make swimming bird swim and then we're just gonna call swim here so now we can say make flying bird fly on our duck and we can make a swimming bird swim on our penguin and you can see that works I can fly and I can swim and this code right here is passing the list cough substitution principle because every subclass of swimming bird is able to properly call this function and every subclass of fly invert in our case duck is able to properly call them make flying bird fly function and everything is working as if it was the parent class the code doesn't know that you have a subclass and because that it needs to work as if it was the parent class but this code has a problem and this is a problem I don't really want to get to in too much depth in this video but it is a major problem with object-oriented programming and inheritance in general and that's that a duck can also swim so a duck can fly and abduct can swim but we can't inherit from two different classes you can't inherit from flying bird and from swimming bird you can only inherit from one of them so what we need to do is maybe create a third class which is a flying swimming bird or something like that and that really doesn't work very well as you get lots and lots of different permutations of flying swimming and other types of birds so what a lot of times you're going to hear about is position which is the idea of adding in functionality instead of inheriting functionality so it would add this swimming functionality to our duck and add the flying functionality to our duck without ever extending any base classes and if composition is something that you want to hear more about make sure to let me know down in the comments below and I'll make an entire video of composition versus inheritance and why composition is so much better than inheritance but for the purposes of this video it's just important to know that as you start following the Liskov substitution principle you may run into issues like this where you have really complex inheritance trees and if you run into that problem you need to look at composition as a way to solve that because inheritance when you get into situations like this can become incredibly messy and is not the best way to write your code but for most instances inheritance is going to work just fine and it's not going to be as complex as this for example all you need to know though for the Liskov substitution principle is that if you have a function that accepts a class every single subclass of that class must also be able to enter that function and work properly that's all there is to the Liskov substitution principle so while the definition is really confusing it's an actually very simple principle to follow and that's all there is to the list cough substitution principle if you enjoyed this video make sure to check out my other videos linked over here and subscribe to my channel for more videos just like this one thank you very much for watching and have a good day
Info
Channel: Web Dev Simplified
Views: 116,699
Rating: undefined out of 5
Keywords: webdevsimplified, SOLID design principles, SOLID design, SOLID design tutorial, SOLID design example, SOLID design explained, SOLID principles javascript, SOLID principles js, solid tutorial JS, JS, javascript, SOLID, liskov principle, liskov substitution principle, liskov substitution principle js, liskov substitution principle javascript, liskov, liskov tuorial, liskov substitution principle tutorial, liskov substitution principle tutorial javascript, liskov principle javascript, js
Id: dJQMqNOC4Pc
Channel Id: undefined
Length: 10min 23sec (623 seconds)
Published: Tue Dec 24 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.