标签列表

everest33

自制力

导航

设计模式平时记录

1. 里式替换原则

1.1 参考文章

1. 2自己理解记录如下:

1.2.※,当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。

class Parent {
    public Map m1(CharSequence cs) {
         System.out.println("父类方法被调用");
    }
}

class Child {
    public HashMap m1(String str) {
        System.out.println("子类方法被调用")
    }
}

class Test {
    public static void main(String[] args) {
        Parent p = new Parent();
        p.m1("Tonus");//使用String类型参数调用父类,父类方法m1中的参数最接近String,所以被调用
       //根据里式替换原则,父类一定要可以被子类无条件替换
       Child c = new Child();
       c.m1("Tonus");//此时子类相当于有两个重载的方法,因为子类参数类型就是String,所以子类会被调用,和原来的“父类被调用”不一致了!!!这就违反了里式替换原则。
如果将父类和子类的参数类型反过来,子类替换父类后,调用的依然是更具体的String类型的父类,所以和原来一直的,符合里式替换原则。
} }

1.2.※,当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。

这个规则不止是里式替换原则中的规则,更是Java本身就规定必须符合的规则。子类返回值类型必须小于等于父类返回值类型(同父类返回值类型相同或是其子类)。如果不符合这条规则编译器会报错。原因是:向上转型在Java中是被允许的,但是向下转型只有被转型的父类本身是子类类型时才被允许,否则运行时报错(编译不报错)。比如 Map map = new HashMap(); //向上转型默认是可以的。但是 HashMap hashMap = new Map(){...};//向下转型默认是不允许的,必须强转(可能会报错)。

继续用上面的代码示例:假如有如下使用场景
class Test {
    public static void main(String[] args) {
         Parent p = new Child();
         Map map = p.m1("Tonus");//此时p.m1()实际上是HashMap,但是编译时被视为Map类型,这里向上转型在Java中是被允许的,无论编译还是运行都不会报错。
如果父类返回HashMap,子类返回Map,那么就会出现向下转型的情况:p.m1();是个Map类型,但是被编译器视为HashMap类型,就出现了Map向下转型为HashMap的场景,
而且这个Map实际并不是HashMap类型,所以使用强转后在运行时会报错(ClassCastException)!
} }

 

1.2.※,子类方法不能降低父类方法的可见性,特别地,如果父类是public,那么子类也必须是public。

这个规则符合里式替换原则,同时也是Java本身就规定必须符合的规则。如果降低了父类方法可见性,父类可以访问的方法子类不能访问就不符合“父类出现的地方一定要被子类无条件替换”的里式替换规则了。

1.3,

posted on 2021-11-26 16:14  everest33  阅读(25)  评论(0编辑  收藏  举报