'The difference between liskov substitution principle and interface segregation principle

Is there any core difference between Liskov Substitution Principle (LSP) and Interface Segregation Principle (ISP)? Ultimately, both are vouching for designing the interface with common functionalities and introduce a new interface when you have special purpose of functionalities.



Solution 1:[1]

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()
}

Solution 2:[2]

The LSP governs relationships between parent and child classes (i.e. hierarchical relationships). It tells you how to implement an API.

The ISP governs relationships between parent and client classes (i.e. producer/consumer relationships). It tells you when to implement an API.

Consider an interface with a hundred methods. A child class could implement all hundred without violating the contracts defined by any of them, and thus satisfying Liskov Substitution; but it's hard to imagine every client would need all of those methods, so Interface Segregation is almost sure to be violated.

Conversely, an interface with only one method surely satisfies Interface Segregation; but if an implementation doesn't obey that one method contract, then Liskov Substitution is violated.

See also: LSP vs DIP

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 jaco0646