Liskov Substitution Principle (LSP)
The Liskov Substitution Principle (LSP) is one of the five object-oriented design principles that form SOLID. It is named after Barbara Liskov, who defined it in 1987.
The principle states that if a type S
is a subtype of type T
, then objects of type T
can be replaced with objects of type S
without affecting the correctness of the program.
In simpler terms, this principle ensures that subtypes can be used interchangeably with their base types.
In programming languages that support inheritance, the LSP helps to establish and maintain a strong and predictable relationship between classes and their subclasses. It allows for polymorphism, where a variable of a base type can refer to an object of any subtype.
For example, consider a scenario where we have an Animal
class and a Dog
class that extends the Animal
class. According to the LSP, we should be able to use an instance of Dog
wherever an instance of Animal
is expected. Let's see an example in Java:
1public class Main {
2 public static void main(String[] args) {
3 Animal animal = new Animal();
4 Dog dog = new Dog();
5 animal.makeSound(); // Output: "Animal is making a sound"
6 dog.makeSound(); // Output: "Dog is barking"
7 animal = new Dog();
8 animal.makeSound(); // Output: "Dog is barking"
9 }
10}
11
12class Animal {
13 public void makeSound() {
14 System.out.println("Animal is making a sound");
15 }
16}
17
18class Dog extends Animal {
19 public void makeSound() {
20 System.out.println("Dog is barking");
21 }
22}
In this example, we have an Animal
class with a makeSound
method that prints "Animal is making a sound". The Dog
class extends the Animal
class and overrides the makeSound
method to print "Dog is barking".
According to the LSP, when we create an instance of Dog
and assign it to a variable of type Animal
, calling the makeSound
method on that variable should still give us the expected behavior. In this case, calling animal.makeSound()
would print "Dog is barking", as expected.
By following the Liskov Substitution Principle, we can ensure that our code is flexible, maintainable, and less prone to bugs. It allows us to write code that can work with multiple types and be easily extended in the future.
xxxxxxxxxx
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
Dog dog = new Dog();
animal.makeSound(); // Output: "Animal is making a sound"
dog.makeSound(); // Output: "Dog is barking"
animal = new Dog();
animal.makeSound(); // Output: "Dog is barking"
}
}
class Animal {
public void makeSound() {
System.out.println("Animal is making a sound");
}
}
class Dog extends Animal {
public void makeSound() {
System.out.println("Dog is barking");
}
}