I'm grappling with understanding the Liskov's Substitution Principle, particularly when it comes to the classic rectangle and square example. The concept of having a base rectangle class and a square class that inherits from it just isn't clicking for me. In this scenario, the setWidth/setHeight methods in the square class are implemented such that setting the width also changes the height to match it.
However, I can't see why this would be a problem. Wouldn't it make sense for a square to have uniform width and height? Moving on, my confusion extends to whether this principle applies to a more complex vehicle/car/plane structure that I've outlined below.
TLDR: I have a car and a plane inheriting the abstract move() method from the Vehicle class. The car increases its x and y location, while the plane adds movement along the z-axis as well. Does this violate the Liskov's Substitution Principle if a function taking a Vehicle class is called to execute the move action? And if so, what makes this a flawed design choice?
I start with an abstract Vehicle class
abstract class Vehicle {
private wheels;
private make;
private seats;
abstract honk(){};
abstract move(){};
}
Followed by subclasses for Car and Plane
Car
class Car extends Vehicle {
private location: Location2d;
public honk() {
console.log(this.getMake() + " IS HONKING");
}
public move(){
this.location.x++;
this.location.y++;
}
}
export default Car;
Plane
class Plane extends Vehicle implements FlyingVehicle {
private maxAltitude;
private location: Location3d;
public honk() {
console.log(this.getMake() + " is HONKING")
}
public move(){
this.location.x++;
this.location.y++;
this.location.z++;
}
}
If there's a function iterating through an array of vehicles calling move on each one, does this go against the Liskov's Substitution Principle?