一、抽象类:有 abstract 关键字修饰的类,称之为抽象类。
1. 抽象类的特点:
① 有 abstract 关键字修饰;
② 含有抽象方法的类,必须声明为抽象类;但是抽象类不一定要含有抽象方法,可以全是非抽象方法;
③ 抽象类必须由子类去继承,进而实现其中所有的抽象方法;若子类没有实现抽象父类中定义的所有抽象方法,那么该子类也需声明为抽象类;
④ 抽象类不能直接实例化,必须通过其子类进行实例化;
⑤ 不能使用 final、private、static 关键字修饰抽象类或抽象方法;
针对第五条特点备注原因:
final 用于修饰属性、方法、类,分别表示属性不可变、方法不能被重写、类不能被继承;这与抽象类是相违背的;
private 修饰的方法,只能在当前类中使用,其访问权限不在子类访问范围之内,所以无法重写;这与抽象类是相违背的;
static 修饰的方法直接通过类名进行调用,那么该方法可能并未由子类实现,这样的方法是没有意义的;
⑥ 除了以上几点之外,抽象类与普通的Java类没有什么区别。
2. 抽象类的作用:
当多个类中出现相同功能,但是功能主题不同的现象时,可以进行向上抽取,只抽取功能的定义而不抽取功能的主体。
抽象类将事物的共性抽取出来,抽象为一个高层的类——抽象父类,由子类分别去实现这些共性的不同操作方式,同时子类也就拥有了父类的属性和方法,继而实现了代码的重用。
子类在继承父类属性和方法的同时,也可以拥有自己独有的属性或者方法,这也就体现了多态的特性。
二、接口:用于规定一个对象/类所应该拥有的公共操作方法的集合。
1. 接口的特点:
① 接口中一般只做方法的声明,必须在对应的实现类中进行具体的实现;
② 接口中可以在定义方法的同时对其进行实现,但是一般习惯上不这么做;
③ 接口中所有方法其实也都是抽象方法,只是省去了 abstract 关键字,接口中的方法默认就是抽象的;
④ 接口中所有方法的访问权限都应是 public、或者 default 级别的;
⑤ 接口中不可以声明普通变量,但可以定义全局的常量,且必须指定初始值,同时常量的访问权限默认是 public static final的;
⑥ 接口可以继承多个接口,那么在该接口的实现类中就必须实现该接口、以及它所继承的所有接口中的方法,否则必须将其声明为抽象类;
三、 抽象类和接口的区别:
① 抽象类和接口都不能直接实例化;
若需要实例化,则抽象类对象必须指向实现了所有抽象方法的子类对象;
接口对象必须指向实现了接口中所有方法的实现类对象;
② 抽象类要被子类继承,接口需要被实现类实现;
③ 抽象类中,既可以做方法的声明,又可以做方法的具体实现,但只做声明的方法为抽象方法必须有abstract关键字修饰;
接口中只能做方法的声明;
④ 抽象类中的变量是普通变量;【抽象类中变量的定义与普通类没有区别】
接口中不能定义变量,只能声明公共的静态常量;【但一般不这么做】
⑤ 抽象类中的抽象方法必须全部被子类所实现,若子类不能完全实现父类抽象方法,那么该子类只能是抽象类;
同样,一个类实现接口时,如果不能实现接口中全部方法,那么这个类也只能为抽象类;
⑥ 抽象类是重构的结果;【抽象方法只能声明,不能实现】
接口是设计的结果;
⑦ 抽象类中可以没有抽象方法;但有抽象方法的类必须定义为抽象类;
四、 抽象类和接口的使用
当关注一个事物的本质时,使用抽象类;而当关注事物的操作时,使用接口;
抽象类的功能要远超过接口,但定义抽象类的代价高。因为高级语言来说(从实际的设计上来说),每个类只能继承一个类。在这个类中,必须继承或编写出其所有子类的所有共性。虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且可以在一个类中同时实现多个接口,在设计阶段的难度会有所降低。