1: Thinking and explanation of inheritance in OO
- Inheritance contains such a meaning: all implemented methods in the parent class are actually setting specifications and contracts. Although it does not force all the subclasses to follow these contracts, if the subclass modifies these implemented methods arbitrarily, it will damage the entire inheritance system.
- Inheritance not only brings convenience to program design, but also brings disadvantages. For example, the use of inheritance will bring intrusion to the program, reduce the portability of the program, and increase the coupling between objects. If a class is inherited by another class, when the class needs to be modified, all the subclasses must be taken into account. After the parent class is modified, all the functions involving subclasses may fail
- The question is: how to use inheritance correctly in programming
2: Basic introduction
- The Liskov Substitution Principle was proposed in 1988 by a woman named Li from MIT.
- If there is object o2 of type T2 for each object o1 of type T1, so that when all objects o1 defined by T1 are replaced by o2, the behavior of program P does not change, then type T2 is a subtype of type T1. In other words, all references to base classes must be able to transparently use objects of their subclasses.
- When using inheritance, follow the principle of leech substitution, and try not to override the methods of the parent class in the child class
- The Riemannian substitution principle tells us that inheritance actually enhances the coupling of the two classes, and that, when appropriate, problems can be solved through aggregation, composition, and dependency. .
Let's look at the following code
Liskov.class
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 idea 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)); } } // Class A class A { // Returns the difference between two numbers public int func1(int num1, int num2) { return num1 - num2; } } // Class B inherits A // A new function has been added: add two numbers and sum with 9 class B extends A { //Here, the class A method is rewritten, which may 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 found that there was an error in the normal subtraction function. The reason is that class B inadvertently rewrites the method of the parent class, resulting in the original function error. In actual programming, we often complete new functions by rewriting the method of the parent class, which is simple to write, but the reusability of the whole inheritance system is poor. Especially when the running polymorphism is frequent
Solution: the original parent class and child class inherit a more popular base class. The original inheritance relationship is removed and replaced by dependency, aggregation, combination and other relationships
Improved code
LiskovImprove.class
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 class B no longer inherits class A, the caller will no longer use func1 to subtract //The function completed by the call will be clear System.out.println("11+3=" + b.func1(11, 3));//The original idea 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)); //Class A related methods can still be used with combination System.out.println("11-3=" + b.func3(11, 3));// The original idea here is to find 11-3 } } //Create a more basic base class class Base { //Write more basic methods and members to Base class } // Class A class A extends Base { // Returns the difference between two numbers public int func1(int num1, int num2) { return num1 - num2; } } // Class B inherits A // A new function has been added: add two numbers and sum with 9 class B extends Base { //If B needs to use method A, use combination relationship private A a = new A(); //Here, the class A method is rewritten, which may 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 method A public int func3(int a, int b) { return this.a.func1(a, b); } }