什么是多态
多态是指实例方法根据调用者会有不同的表现,就像多种形态一样。这里要注意的是:静态方法没有多态的说法。
可以看到,虽然都是 Person 类,但是 p1 是真正的 Person,而 p2 是 Person 的子类,子类中又 Override 了父类的方法,所以虽然看上去都是调用 sayHi 方法,但是有着不同的表现,这就是多态的体现了。
什么是抽象类
抽象类的本质仍然是个类,所以类可以有的东西,它也可以有,此外它还可以声明抽象方法。
声明抽象方法应该要注意:抽象方法不能是 private 或者是 static. 这个也可以理解。如果是 private 的话,那么子类就无法重写了。
如果是 static 的话,那就意味着可以被直接调用,但是很明显抽象方法没有方法体,不能被直接调用。
为什么要使用抽象类
先假设我们没有抽象类,我们要实现一个需求:
有一个 Person 类,他有 sayHi 方法,供子类使用,还有一个 work 方法,由于不知道子类的具体实现,所以留空。
那么我们会写出这样的代码:
但是即使子类不重写的话,编译不会报错,那如果我们改成抽象类的话,子类就必须实现。
所以抽象类就像是「模板方法」,它预留了几个方法空位,让子类自行实现。
什么是接口
如果一个抽象类中的方法都是抽象方法,那么就应该可以把它声明为接口。
接口中也可以包含成员,但是成员都是 public static final 的,即常量。
我们在 IDEA 中写的时候,会看到它显示灰色,那么就表示我们不用显式地声明。
为什么要使用接口
我们都知道,Java 中的类只能继承一个类。有时候我们会遇到一些非常“不同寻常”的需求:一个 Person 类。
一个 Programer 类继承 Person。
一个 Teacher 类继承 Person。
问题来了,如果我想要一个「会编程的老师」怎么办...
Java 中一个类可以实现多个接口,所以弥补了这个短板。
但是接口有一个非常非常明显的弊端:接口一旦发布,就无法更改了。
怎么理解这句话呢?比如 A 接口有 B、C、D 三个方法,那么我继承了 A 接口并且实现了这些方法。假如有一天 A 接口要增加一个 E 方法,如果我不跟着改动,那么我的代码就报错了,因为实现接口的时候必须要实现接口的所有抽象方法。
为了这个问题,Java8 引入了接口的默认方法。但是在传统的面向对象编程的思想中,接口应该只包含抽象方法。
内部类和静态内部类
内部类是指我们在类中又定义了一个类,一般是起到更好的封装效果。
内部类可以选择是否用 static 修饰符来修饰,两者的区别就是是否包含一个外部类的引用,非静态内部类是包含外部类的引用的,而静态内部类是不包含外部类的引用的。
我们推荐使用「静态内部类」,因为可以减少大小,如果编译报错,那么就去掉 static 修饰符。