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 functioncallBaba()
which get your father phone number then calls him, So you must make sure that thecallBaba()
method in all subclasses of theDevice
does the same job. if any of the subclasses ofDevice
have another behavior insidecallBaba()
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()
}