This is the 31st day of my participation in the August Text Challenge.More challenges in August
Richter’s substitution principle
define
1. In layman’s terms, a subclass extends the functionality of its parent class, but does not change the functionality of its parent class.
2. Replace a superclass object with a subclass object in the program, the program will not generate any errors and exceptions, the reverse is not true.
3. It is one of the important ways to realize the open and close principle. Because the use of base class objects can use subclass objects, the program tries to use the parent class type to define the object, and then establish the subclass type at run time, and replace the parent class object with the subclass object.
The implications of The Richter substitution principle
1. A subclass can implement abstract methods of its parent class, but cannot override non-abstract methods of its parent class.
2. Subclasses can add their own special methods.
3. When a subclass overrides or implements a superclass method, method preconditions (parameters) are looser than those of the superclass method. 4. When a subclass’s method implements the (abstract) method of the parent class, the postcondition (that is, the return value of the method) is stricter than that of the parent class.
The role of inheritance
1. Improve code reuse
2. The premise of polymorphism
Methods to rewrite
The same return value type, method name, and parameter list constitute method rewriting
Two limitations of method rewriting
1. When a subclass overrides a parent class method, its access modifiers cannot be stricter than those of the parent class. example
public class TestExtends {
public static void main(String[] args) {
Father f=newFather(); f.method1(); }}class Father{
public void method1(a){}}class Son extends Father{}Copy the code
Now we’re going to replace the parent object with a subclass object, and that’s fine
public class TestExtends {
public static void main(String[] args) {
Father f=newFather(); f.method1(); }}class Father{
public void method1(a){}}class Son extends Father{}Copy the code
Overrode parent class method1, found an error
Here’s why
public static void main(String[] args) {
Father f=new Son();
f.method1();
}
Copy the code
The parent’s method1() method was already callable. If we had replaced the parent with a subclass object that had less access to it than the parent, we would not have been able to call it and would not have been able to do so in violation of the Reefer substitution principle.
2. When a subclass overrides a method of its parent class, the subclass method cannot throw more exceptions than the parent class.
public class TestExtends {
public static void main(String[] args) {
Father f=new Son();
try {
f.method1();
} catch (Exception e) {
// TODO Auto-generated catch blocke.printStackTrace(); }}}class Father{
public void method1(a) throws IOException{}}class Son extends Father{
public void method1(a) {}}Copy the code
So in this program, the parent class’s method1 method throws an I/O exception, so when we call it, we try catch it, and if the subclass method doesn’t throw an exception, the subclass object can just replace the parent. But if the parent class’s method1 method does not throw an exception, and the subclass method does when overridden, you can see the program report an error
This is because we don’t need a try catch when we call a superclass method, but we need a try catch when we replace it with a subclass object. In this case, references to the superclass cannot transparently use the subclass object. So we’re not allowed to rewrite methods like this.
What is the reason why two classes cannot inherit
A. Whether or not “is A “matters
B. After the two classes have the “is A “relationship, it is necessary to consider whether the business logic of the subclass object changes after replacing the parent class object. If it changes, the inheritance relationship cannot occur.
Square and rectangle have “is A “relation.
Business scenarios need to be considered. In a particular business scenario, replacing rectangles with squares may lead to changes in business logic.
public class LiskovSubstitutionPrincipleTest {
public static void main(String[] args) {
Rectangle r=new Rectangle();
r.setLength(20);
r.setWidth(15);
System.out.println("Length:"+r.getLength()+","+"Width:"+r.getWidth());
Utils.change(r);
System.out.println("Length:"+r.getLength()+","+"Width:"+r.getWidth());
Rectangle square=new Square();
square.setLength(12);
System.out.println("Length:"+square.getLength()+","+"Width:"+square.getWidth());
Utils.change(square);
System.out.println("Length:"+square.getLength()+","+"Width:"+square.getWidth()); }}class Rectangle{
public double length;
public double width;
public double getLength(a) {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double getWidth(a) {
return width;
}
public void setWidth(double width) {
this.width = width; }}class Square extends Rectangle{
public double getLength(a) {
return length;
}
public void setLength(double length) {
this.length = length;
this.width=length;
}
public double getWidth(a) {
return width;
}
public void setWidth(double width) {
this.width = width;
this.length=width; }}class Utils{
public static void change(Rectangle r) {
while(r.getWidth()<=r.getLength()) {
r.setWidth(r.getWidth()+1);
System.out.println("Length:"+r.getLength()+","+"Width:"+r.getWidth()); }}}Copy the code
Logical analysis
The business scenario we need to implement here is to increase the width of the rectangle until the width is 1 more than the length, but the square length equals the width property prevents us from implementing this business scenario, that is, the subclass object replaces the parent class object, changing the original business logic. So a square cannot subclass a rectangle in this scenario.