一. 抽象类的特性(语法规则)
- 抽象类不能被实例化
注:为什么抽象类不能被实例化?
从语义上来解释,抽象类表示的从具体类型抽象出来的类型,例如苹果类、香蕉类和橘子类是具体类,而水果类则是抽象类,在自然界中也不存在水果类本身的实例。 - 抽象类中可以没有抽象方法
- 包含抽象方法的类必须被定义为抽象类,如果子类没有实现父类中所有的抽象方法,子类也必须被定义为抽象类。
abstract class Base{
abstract void method1();
abstract void method2();
}
class Sub extends Base{
void method1(){System.out.println("method1");}
} // 编译出错,Sub类必须声明为抽象类。
- abstract修饰符不能与static修饰符连用修饰方法(abstract只能修饰类,方法;static只能修饰方法,变量,代码块,ps:static可以修饰内部类)
注:为什么abstract修饰符不能与static修饰符连用?
若一个方法用abstract修饰,则表示为抽象方法,没有方法体,需要被继承的子类实现;若一个方法用static修饰,则表示某个类所特有的功能,这种功能的实现不依赖于类的具体事例,更不依赖于它的子类,当前类必须为静态方法提供实现的机会。
二. 接口的特性(语法规则)
- 接口中的成员变量,必须是public访问级别,并且是static、final类型,必须被显式地初始化。
public interface StandardIFC{
public static final int MAX_AGE = 120;
int MIN_AGE = 1; // 默认是 public static final 类型。
private int TOTEL = 2; // 编译错误,接口中不允许出现private访问级别的成员变量
}
- 接口中的成员方法,必须是public或private访问级别。
- 一个接口可以继承多个其它接口。
- 接口必须通过类来实现它的抽象方法。
- 一个类只能继承一个直接的父类,但能实现多个接口。
- 不允许创建接口的实例,但可以声明接口类型的变量来引用实现了这个接口的实例。
CalculatorIFC cal = new Calculator(); // Calculator类实现了CalculatorIFC接口
这里提一下多态的定义:一个引用类型的变量可以引用声明类型的实例,还可以引用其子类型的实例,这样,这个变量就有多种状态。当调用它的实例方法时,到底是调用父类还是子类的实例方法,取决于这个变量实际上引用的实例。
三. 比较抽象类与接口
抽象类与接口的相同点:
- 都不能被实例化。
- 都能包含抽象方法和非抽象方法。
抽象类与接口的不同点:
- 接口中的成员变量之能事public、static和final类型;而在抽象类中可以定义各种类型各种访问级别的成员变量。(抽象类的优势)
- 一个类只能继承一个直接父类;但一个类可以实现多个接口。(接口的优势)
- 二者本质上的区别:对于任意2个及以上的类,不管它们是否属于同一个父类,只要存在着相同的功能,就能抽象出一个接口类型。举例:风筝类(Kite)和鸟类(Bird)无法抽象出一个抽象父类,但是存在相同的功能,都能飞,因此可以抽象出一个飞(Flyable)的接口类型。
- 继承抽象类的子类主要是做一些扩展功能和实现功能的工作;而继承接口的类只是做实现功能的工作。