Richter substitution principle
Thinking and explanation of inheritance in IOO
-
Inheritance contains such a meaning: all implemented methods in the parent class are actually setting specifications and contracts. Although it does not force all subclasses to follow these contracts, if subclasses arbitrarily modify these implemented methods, it will destroy the whole inheritance system.
-
Inheritance not only brings convenience to programming, but also brings disadvantages. For example, using inheritance will bring invasiveness to the program, reduce the portability of the program and increase the coupling between objects. If a class is inherited by other classes, all subclasses must be considered when the class needs to be modified, and all functions involving subclasses may fail after the parent class is modified
-
The question is: how to use inheritance correctly in programming? = > Richter substitution principle
Basic introduction
-
The Liskov Substitution Principle was proposed by a woman surnamed Li of MIT in 1988.
-
If there is object o2 of type T2 for each object o1 of type T1, so that the behavior of program P does not change when all objects o1 are replaced with o2, then type T2 is a subtype of type T1. In other words, all references to the base class must be able to use the objects of its subclasses transparently.
-
When using inheritance, follow the Richter substitution principle and try not to override the methods of the parent class in the subclass
-
The Richter substitution principle tells us that inheritance actually enhances the coupling between the two classes. In appropriate cases, the problem can be solved through aggregation, composition and dependency.
Problems and thoughts caused by a program
Let's look at the procedure first and think about the problems and solutions
code:
package com.atguigu.principle.liskov; public class Liskov { public static void main(String[] args) { // TODO Auto-generated method stub A a = new A(); System.out.println("11-3=" + a.func1(11, 3)); System.out.println("1-8=" + a.func1(1, 8)); System.out.println("-----------------------"); B b = new B(); System.out.println("11-3=" + b.func1(11, 3));//The original intention here is to find 11-3 System.out.println("1-8=" + b.func1(1, 8));// 1-8 System.out.println("11+3+9=" + b.func2(11, 3)); } } // A class class A { // Returns the difference between two numbers public int func1(int num1, int num2) { return num1 - num2; } } // B Class inherits A // Added a new function: complete the addition of two numbers,Then sum with 9 class B extends A { //Here, rewrite A Class method, Maybe unconscious public int func1(int a, int b) { return a + b; } public int func2(int a, int b) { return func1(a, b) + 9; } }
resolvent
-
We found an error in the subtraction function that was working normally. The reason is that class B inadvertently rewrites the method of the parent class, resulting in errors in the original function. In actual programming, we often complete new functions by rewriting the parent class. Although it is simple to write, the reusability of the whole inheritance system will be poor. Especially when running polymorphism more frequently
-
The common approach is: the original parent and child classes inherit a more popular base class, remove the original inheritance relationship, and replace it with dependency, aggregation, composition and other relationships
- Improvement plan:
code:
package com.atguigu.principle.liskov.improve; public class Liskov { public static void main(String[] args) { // TODO Auto-generated method stub A a = new A(); System.out.println("11-3=" + a.func1(11, 3)); System.out.println("1-8=" + a.func1(1, 8)); System.out.println("-----------------------"); B b = new B(); //because B Class no longer inherits A Class, so the caller will no longer func1 It's subtraction //The function completed by the call will be clear System.out.println("11+3=" + b.func1(11, 3));//The original intention here is to find 11+3 System.out.println("1+8=" + b.func1(1, 8));// 1+8 System.out.println("11+3+9=" + b.func2(11, 3)); //The combination can still be used A Class correlation method System.out.println("11-3=" + b.func3(11, 3));// The original intention here is to find 11-3 } } //Create a more basic base class class Base { //Write more basic methods and members to Base class } // A class class A extends Base { // Returns the difference between two numbers public int func1(int num1, int num2) { return num1 - num2; } } // B Class inherits A // Added a new function: complete the addition of two numbers,Then sum with 9 class B extends Base { //If B Need to use A Class method,Use composite relationships private A a = new A(); //Here, rewrite A Class method, It could be unconscious public int func1(int a, int b) { return a + b; } public int func2(int a, int b) { return func1(a, b) + 9; } //We still want to use A Method of public int func3(int a, int b) { return this.a.func1(a, b); } }