@@ -861,6 +861,144 @@ class AjaxRequester {
861861```
862862** [ ⬆ back to top] ( #table-of-contents ) **
863863
864+
865+ ### Liskov Substitution Principle (LSP)
866+ This is a scary term for a very simple concept. It's formally defined as "If S
867+ is a subtype of T, then objects of type T may be replaced with objects of type S
868+ (i.e., objects of type S may substitute objects of type T) without altering any
869+ of the desirable properties of that program (correctness, task performed,
870+ etc.)." That's an even scarier definition.
871+
872+ The best explanation for this is if you have a parent class and a child class,
873+ then the base class and child class can be used interchangeably without getting
874+ incorrect results. This might still be confusing, so let's take a look at the
875+ classic Square-Rectangle example. Mathematically, a square is a rectangle, but
876+ if you model it using the "is-a" relationship via inheritance, you quickly
877+ get into trouble.
878+
879+ ** Bad:**
880+ ``` javascript
881+ class Rectangle {
882+ constructor () {
883+ this .width = 0 ;
884+ this .height = 0 ;
885+ }
886+
887+ setColor (color ) {
888+ // ...
889+ }
890+
891+ render (area ) {
892+ // ...
893+ }
894+
895+ setWidth (width ) {
896+ this .width = width;
897+ }
898+
899+ setHeight (height ) {
900+ this .height = height;
901+ }
902+
903+ getArea () {
904+ return this .width * this .height ;
905+ }
906+ }
907+
908+ class Square extends Rectangle {
909+ constructor () {
910+ super ();
911+ }
912+
913+ setWidth (width ) {
914+ this .width = width;
915+ this .height = width;
916+ }
917+
918+ setHeight (height ) {
919+ this .width = height;
920+ this .height = height;
921+ }
922+ }
923+
924+ function renderLargeRectangles (rectangles ) {
925+ rectangles .forEach ((rectangle ) => {
926+ rectangle .setWidth (4 );
927+ rectangle .setHeight (5 );
928+ let area = rectangle .getArea (); // BAD: Will return 25 for Square. Should be 20.
929+ rectangle .render (area);
930+ })
931+ }
932+
933+ let rectangles = [new Rectangle (), new Rectangle (), new Square ()];
934+ renderLargeRectangles (rectangles);
935+ ```
936+
937+ ** Good** :
938+ ``` javascript
939+ class Shape {
940+ constructor () {}
941+
942+ setColor (color ) {
943+ // ...
944+ }
945+
946+ render (area ) {
947+ // ...
948+ }
949+ }
950+
951+ class Rectangle extends Shape {
952+ constructor () {
953+ super ();
954+ this .width = 0 ;
955+ this .height = 0 ;
956+ }
957+
958+ setWidth (width ) {
959+ this .width = width;
960+ }
961+
962+ setHeight (height ) {
963+ this .height = height;
964+ }
965+
966+ getArea () {
967+ return this .width * this .height ;
968+ }
969+ }
970+
971+ class Square extends Shape {
972+ constructor () {
973+ super ();
974+ this .length = 0 ;
975+ }
976+
977+ setLength (length ) {
978+ this .length = length;
979+ }
980+ }
981+
982+ function renderLargeShapes (shapes ) {
983+ shapes .forEach ((shape ) => {
984+ switch (shape .constructor .name ) {
985+ case ' Square' :
986+ shape .setLength (5 );
987+ case ' Rectangle' :
988+ shape .setWidth (4 );
989+ shape .setHeight (5 );
990+ }
991+
992+ let area = shape .getArea ();
993+ shape .render (area);
994+ })
995+ }
996+
997+ let shapes = [new Rectangle (), new Rectangle (), new Square ()];
998+ renderLargeShapes ();
999+ ```
1000+ ** [ ⬆ back to top] ( #table-of-contents ) **
1001+
8641002### Prefer ES6 classes over ES5 plain functions
8651003It's very difficult to get readable class inheritance, construction, and method
8661004definitions for classical ES5 classes. If you need inheritance (and be aware
0 commit comments