There must be many people who are confused about this principle, just like when I first saw it. The fact is that this principle was first proposed in 1988 by a lady surnamed Barbara liskov at the Massachusetts Institute of Technology.
Definition 1:Assume that there is an object O2 of Type T2 for each type of T1 object O1, so that all program P defined by T1 can be replaced by O2 when all object O1 is replaced by O2, if the behavior of program P does not change, Type T2 is the child type of Type T1.
Definition 2:All objects that reference the base class must be transparently used.
Problem:There is a function P1, completed by Class. Now you need to extend the function P1. The extended function is P, which consists of the original function P1 and the new function P2. When the new function P is completed by subclass B of Class A, when subclass B completes the new function P2, it may cause problems with the original function P1.
Solution:When using inheritance, follow the Lee's replacement principle. When Class B inherits Class A, in addition to adding a new method to add the new function P2, try not to override the method of parent class A, and try not to reload the method of parent Class.
Inheritance includes the following meanings: Any method in the parent class that has been implemented (relative to the abstract method) is actually setting a series of norms and contracts, although it does not require all subclasses to comply with these contracts, it is assumed that the subclass will change these non-Abstract METHODS at will, which will damage the entire inheritance system. The principle of Lishi replacement is to express this layer of meaning.
Inheritance, as one of the three main characteristics of object-oriented programming, brings huge convenience at the same time, but also brings disadvantages. For example, using inheritance will introduce intrusion to the program, reduce program portability, and add coupling between objects. Assume that a class is inherited by other classes, when this class needs to be changed, all child classes must be taken into account. After the parent class is changed, all functions involving child classes may fail.
For example, to illustrate the risk of inheritance, we need to complete a two-digit subtraction function, which is the responsibility of Class.
class A{public int func1(int a, int b){return a-b;}}public class Client{public static void main(String[] args){A a = new A();System.out.println("100-50="+a.func1(100, 50));System.out.println("100-80="+a.func1(100, 80));}}
Execution result:
100-50 = 50
100-80 = 20
Later, we need to add a new function: After adding two numbers, We Need To sum them with 100, and Class B is responsible for this. Class B requires two functions:
- Subtract two numbers.
- Add two numbers, and then add 100.
Because Class A has implemented the first function, after class B inherits Class A, it only needs to complete the second function. The Code is as follows:
class B extends A{public int func1(int a, int b){return a+b;}public int func2(int a, int b){return func1(a,b)+100;}}public class Client{public static void main(String[] args){B b = new B();System.out.println("100-50="+b.func1(100, 50));System.out.println("100-80="+b.func1(100, 80));System.out.println("100+20+100="+b.func2(100, 20));}}
After class B is completed, the execution result is:
100-50 = 150
100-80 = 180
100 plus 20 + 100 = 220
We found that an error occurred while performing the normal subtraction function. The reason is that Class B accidentally overwrites the method of the parent class when naming the method, causing all the code executing the subtraction function to call the method after Class B's rewriting, an error occurred while executing the function normally. In this example, the function of referencing base class A is replaced by subclass B, and an exception occurs. In actual programming, we often rewrite the parent class method to complete new functions. Although it is simple to write, the reusability of the entire inheritance system is worse than least, in particular, when polymorphism is used more frequently than failover, the chance of program execution errors is very high. Assume that you have to override the parent class method. The common practice of this method is: the original parent class and subclass both inherit a more popular base class, and the original inheritance relationship is removed, dependencies are replaced by dependency, aggregation, and combination.
In general, the Lee's replacement principle is:Sub-classes can expand the features of the parent class, but cannot change the original features of the parent class.It includes the following four meanings:
- Sub-classes can implement abstract methods of parent classes, but cannot overwrite non-Abstract methods of parent classes.
- Sub-classes can add their own unique methods.
- When the method of the subclass reloads the method of the parent class, the precondition of the method (that is, the form of the method) is looser than the number of input partitions of the parent class method.
- When the subclass method implements the abstract method of the parent class, the post-condition (that is, the return value of the method) of the method is stricter than that of the parent class.
It looks incredible, because we will find that our own programming often violates the Lee's replacement principle, and the program runs well. So everyone will have such questions. What would happen if I did not follow the Lee's replacement principle?
The consequence is:The probability of a problem in the code you write will be greatly increased.