里氏替换原则究竟如何理解?


 

  • SOLID
    • SRP 
    • OCP 
    • LSP 
    • ISP 
    • DIP 
  • DRY 
  • KISS 
  • YAGNI 
  • LOD 

 


 

论,方法结构的约束和方法逻辑约束。下面我们逐个深入讨论

 

1. 方

1.1 

 P  P  P  

 

   AB C  B  C  A B P C  P2足法则。

使

 A  test  P  C  A  test  P C  test  p2Method 

 P  P2 

class P {
    private void method(){};
}

class P1 extend P {
}

class P2 extend P1{
    private void p2Method(){};
}

class A {
    private void test(P1 p){};
}

// 符合
class B extend A {
    private void test(P p){};
}

// 不符合
class C extend A {
    private void test(P2 p){
        p.p2Method();
    };
}


P p = new P();

A a = new A();
a.test(p);

C c = new C();
// 执行失败,因为 P 没有 p2Method 方法。如果用c替换掉a,则会失败
c.test(p);

 

1.2 返回值不能比父类宽松

 

 

A R1 B R2  C  R 

 A  test R1 r1Method  C  A C test  Rr1Method


class R {
    private void method(){};
}

class R1 extend R {
    private void r1Method(){};
}

class R2 extend R1{
    private void r2Method(){};
}

class A {
    private R1 test(){
        ...
    };
}

// 符合
class B extend A {
    private R2 test(){
        ...
    };
}

// 不符合
class C extend A {
    private R test(){
        ...
    };
}


A a = new A();
R1 r = a.test();
r.r1Method();

C c = new C();
R1 r = c.test(p);
// 执行失败,因为 c.test 的返回值实际上是 R 类,没有 r1Method 方法
r.r1Method();

 

 

 

2. 方

 

2.1 对入参的逻辑处理不能比父类严格

 

PP1P2 P1  P2  P  

A  test   P B  A  B  test  
 B  test  P  B  test  P2

class P {
    private void method(){...};
}

class P1 extend P {
    private void p1Method(){...};
}

class P2 extend P {
    private void p2Method(){...};
}

class A {
    private void test(P p){...};
}

class B extend A {
private void test(P p){    // 这里做了强制转换    P1 p = (P1)p;
    p.p1Method();
};
}


// 这样处理没问题
P p = new P1();
A a = new B();
a.test(P1);

// 但如果入参是 P2,就会报错了。因为B类中,会将入参强制转换成 P1,类型转换失败
P p = new P2();
A a = new B();
a.test(P1);

  

 

 P1  使 P1  

 P1  P B  test 

 i<0  i<=0 i=0  B  A  i=0 

 

class A {
    private void test(int i){
        if(i < 0){            throw new RuntimeException();        }                ...    };
}

class B extend A {
    private void test(int i){
        // 包括0的场景,即比父类严格        if(i <= 0){           throw new RuntimeException();
        }
       ...};};


int i = 0;
A a = new A();
A b = new B();

// 不报错
a.test(i);

// 抛异常。即如果用b替代a的位置,程序会抛异常
b.test(i)

 

2.2 返回值的逻辑不能比父类宽松

 

A  runTask  1 0B  2
2

 
class A { 

   private int runTask(List<Task> tasks) {

          ...        

          boolean success = false;        

          for(Task task:tasks){          

            success = task.run();          

            if(!success){

               break;          

            }        

          }                

          if(success){     

            return 1;        

          } else if(!success){

            return 0;        

          }    

   }

}

 

class B extend A {

  private int runTask(List<Task> tasks){

      ...        

      // 如果入参为空,直接返回2,表示忽略  

      if(CollectionUtils.isEmpty(tasks)){   

        return 2;        

      }

      boolean success = false;

      for(Task task:tasks){

        success = task.run();

        if(!success){

          break;          

        }        

        if(success){

          return 1;          

        } else if(!success){

          return 0;        

        }    

      }

  }

}

 

2.3 不能违背函数声明的语义 

 


 

 JAVA 

使

 

 

结尾

 i<=0  i<0 

 


 


微信搜索公众号 架入豪文 

 



 

posted @ 2023-06-13 09:08  架入豪文  阅读(129)  评论(0)    收藏  举报