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.

- 15,303
- 7
- 59
- 83

- 451
- 4
- 6
-
if its related to interface,use ISP but if its related to classes and extended classes,use LSP. – Savannah Madison Apr 11 '22 at 10:26
3 Answers
LSP: The subtype must honor the contracts it promises.
ISP: The caller shouldn't depend on more of the base type'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."

- 20,545
- 2
- 64
- 95
-
1The *receiver* term is quite confusing to me. Can't get it. Could you call it something else? *subtype*? – ClemC Nov 25 '19 at 15:32
-
3Could that be resumed as: *Liskov Substitution* addresses **subtypes** design whereas *Interface Seggregation* addresses **basetypes** design.? – ClemC Nov 25 '19 at 16:19
-
1By receiver, I mean the object receiving a message. It may or may not be a subtype. Yes, I think your characterization makes sense, about subtype vs. base type. – Jon Reid Nov 25 '19 at 18:07
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()
}

- 962
- 10
- 14
-
Seems the same to me? both solve the problem by seperating the functions to different interfaces or different abstract classes – Jono Nov 26 '20 at 11:07
-
2
-
@jonathan you could have an interface with a single function and still break its purpose. Imagine I implement the Flyable interface and add swimming logic in the fly() method. Interface segregation is already fine because I can segregate it even further, but the LSP is broken because I'm not adding the right behavior – AFP_555 May 30 '21 at 16:30
-
They are both the same. There's no way to know if it's doing what it's intention to do without actually unit testing it and it producing a output – Jono May 30 '21 at 18:23
-
1@Jonathan I'll give you a simple example. Imagine I have a class Duck with an abstract method fly(), and a RubberDuck that inherits from that class. The RubberDuck can't fly, so instead of flying it throws an exception in this method. This is also breaking the LSP because we're not adding the expected behavior, we're just throwing an exception. Or, imagine we add floating logic in the fly() method, that's also breaking LSP. – AFP_555 Jun 02 '21 at 23:16
-
@Jonathan in simple words, LSP is about checking if the methods do what they are supposed to do. ISP is about not depending on more method than necessary. There is a HUGE overlap between these two things, in fact, there is more overlap than difference, but they are not the same thing. It is like many patterns, for example, the Strategy Pattern is very similar to the Bridge pattern, but their intention is different. Structurally they are the same, they kinda do the same behaviorally, but the idea behind them is different. Usually if LSP is broken, ISP is also broken, but not always. – AFP_555 Jun 02 '21 at 23:29
-
if the method doesnt do what its suppsoed to do then it invalidates IPS as well because you are supposed to only inherit interfaces a class will use – Jono Jun 03 '21 at 10:02
-
In your callBaba function, which is then invoked in something else which invokes via the base class if your implementation still 'called baba' but it did it differently wouldnt this equate to a change in behaviour? This is the line I find impossible to comprehend, what if function A takes a Device, it currently implements the callBaba method and it uses the smart phone functionality, but later someone overrides it in a new impl and it now still calls baba but it does it via Skype for instance, now this new impl is substituted, doesnt this equate to a change in behaviour for function A? – berimbolo Sep 10 '21 at 06:11
-
What is actually meant by behaviour because for example if one implementation of a function is extremely fast and its called inside some other function meaning it runs quickly, and now that function is given a substitute which does the same thing but it does it in 10 x the time, this means the behaviour of the function is no longer entirely the same, it was fast and it is now slow, even if the end result is the same. ~ How is behaviour defined? – berimbolo Sep 10 '21 at 06:14
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

- 15,303
- 7
- 59
- 83
-
You say the implementation 'doesn't obey the method contract' but how can this be possible as the contract is defined? More often people talk about the 'behaviour' of an implementation rather than the contract when talking about LSP, but how is this is even possible to achieve in reality. If I have a method that takes some type T, and part of its behaviour is its quick, and I then override a called implementation in some other class, implement it according to the contract but it is slow (maybe it gets data from a file now), I have changed its behaviour ? – berimbolo Sep 10 '21 at 06:05
-
The point is simply that a single method can produce an LSP violation, but it _cannot_ produce an ISP violation, which highlights a difference between these two principles. Precisely _how_ an LSP violation occurs is based on, "...a number of behavioural conditions. These are detailed in a terminology resembling that of design by contract..." [Wikipedia](https://en.wikipedia.org/wiki/Liskov_substitution_principle#Principle) @berimbolo – jaco0646 Sep 10 '21 at 17:15
-
Read that page again and it makes a little more sense, so correctness would mean in my example the item is retrieved, speed is not a factor because the method still functions as it should. Do you understand the covariance for argumentvs vs contravariance for return types? Does this mean that an argument (in) can be a more specific type in a sub type (but not more general) but that a return type can be more general (but not more specific)? – berimbolo Sep 11 '21 at 07:00
-
@berimbolo, these are good questions for a new thread. I don't want to get into details of the LSP here, because I think my answer shows these two SOLID principles are trivially and obviously different. Detailed definitions are unnecessary to answer the OP's question and prove the LSP and the ISP are not the same. – jaco0646 Sep 13 '21 at 13:23