I have heard that the Liskov Substitution Principle (LSP) is a fundamental principle of object oriented design. What is it and what are some examples of its use?
相关问题
- how to define constructor for Python's new Nam
- Keeping track of variable instances
- Object.create() bug?
- std::vector of objects / pointers / smart pointers
- Name for a method that has only side effects
相关文章
- 接口B继承接口A,但是又不添加新的方法。这样有什么意义吗?
- NameError: name 'self' is not defined, eve
- Implementation Strategies for Object Orientation
- Check if the Type of an Object is inherited from a
- When to use Interfaces in PHP
- Are default parameters bad practice in OOP?
- How to return new instance of subclass while initi
- In OOP, what is the best practice in regards to us
The clearest explanation for LSP I found so far has been "The Liskov Substitution Principle says that the object of a derived class should be able to replace an object of the base class without bringing any errors in the system or modifying the behavior of the base class" from here. The article gives code example for violating LSP and fixing it.
The LSP is a rule about the contract of the clases: if a base class satisfies a contract, then by the LSP derived classes must also satisfy that contract.
In Pseudo-python
satisfies LSP if every time you call Foo on a Derived object, it gives exactly the same results as calling Foo on a Base object, as long as arg is the same.
let's do a simple example in Java:
Bad example
The duck can fly because of it is a bird, But what about this:
Ostrich is a bird, But it can't fly, Ostrich class is a subtype of class Bird, But it can't use the fly method, that means that we are breaking LSP principle.
Good example
This formulation of the LSP is way too strong:
Which basically means that S is another, completely encapsulated implementation of the exact same thing as T. And I could be bold and decide that performance is part of the behavior of P...
So, basically, any use of late-binding violates the LSP. It's the whole point of OO to to obtain a different behavior when we substitute an object of one kind for one of another kind!
The formulation cited by wikipedia is better since the property depends on the context and does not necessarily include the whole behavior of the program.
Would implementing ThreeDBoard in terms of an array of Board be that useful?
Perhaps you may want to treat slices of ThreeDBoard in various planes as a Board. In that case you may want to abstract out an interface (or abstract class) for Board to allow for multiple implementations.
In terms of external interface, you might want to factor out a Board interface for both TwoDBoard and ThreeDBoard (although none of the above methods fit).
Let's say we use a rectangle in our code
In our geometry class we learned that a square is a special type of rectangle because its width is the same length as its height. Let's make a
Square
class as well based on this info:If we replace the
Rectangle
withSquare
in our first code, then it will break:This is because the
Square
has a new precondition we did not have in theRectangle
class:width == height
. According to LSP theRectangle
instances should be substitutable withRectangle
subclass instances. This is because these instances pass the type check forRectangle
instances and so they will cause unexpected errors in your code.This was an example for the "preconditions cannot be strengthened in a subtype" part in the wiki article. So to sum up, violating LSP will probably cause errors in your code at some point.