The difference between liskov substitution principle and interface segregation principle

LSP: The receiver must honor the contracts it promises.

ISP: The caller shouldn't depend on more of the receiver's interface than it needs.

Where they fit: If you apply the ISP, you use only a slice of the receiver's full interface. But according to LSP, the receiver must still honor that slice.

If you fail to apply ISP, there can be a temptation to violate LSP. Because "this method doesn't matter, it won't actually be called."


Both of them are SOLID principles

  • LSP (Liskov Substitution): this principle asks you to make sure that all child classes have the same behavior as the parent class. for example: if you have a Device class and it has function callBaba() which get your father phone number then calls him, So you must make sure that the callBaba() method in all subclasses of the Device does the same job. if any of the subclasses of Device have another behavior inside callBaba() this is mean you broke the LSP

Example of code that breaks Liskov Principle.

class Device {
    func callBaba() {
        print("I will find your father and I will call him")
    }
}

class Calculator: Device {
    override func callBaba() {
      print("Sorry, I don't have this functionality ")
    }
}

The Solution

interface CanCall {
            func callBaba()
        }
        class Device {
            // all basic shared functions here.
        }

        class Calculator: Device {
            // all functions that calculator can do + Device
        }
        class SmartPhone: Device implements CanCall {
            // all smartphone stuff
            func callBaba() {
                print("I will find your father and I will call him")
            }
        }
  • ISP (Interface Segregation): Asks you to create a different interface for different responsibilities, in other words, don't group unrelated behavior in one interface, You break ISP if You have already an interface with many responsibilities, and the implementor doesn't need all this stuff

this breaks ISP principle because it has two different responsibilities

  protocol Animal {
        func fly()
        func eat()
    }

The Solution

protocol Flyable {
    func fly()
}
protocol Feedable {
    func eat()
}