【老白学 Java】抽象类和抽象方法
抽象类和抽象方法
文章来源:《Head First Java》修炼感悟。
在上一篇文章中,老白见识到了多态的威力,学会了如何应用多态。 随着学习的深入,老白认为那些不过是多态的基本招式,接口才是真正的绝招。 接下来老白将继续探索 Java 的接口,不过在这之前,首先需要弄清楚什么是抽象类。
什么是抽象类
在学习继承的这段时间,老白产生了一个疑问:既然继承只是提供一个协议,好像没有什么理由创建父类的实例对象,比如:
Animal animal = new Animal();
这个引用变量 animal
代表着什么呢,又要如何使用它呢? 实在想不通为什么要创建它。 那么有没有一种手段,限制创建实例对象? 万幸的是,真的有这种方法,而且很简单,只要在类声明前加上 abstract
关键字,就像这样:
abstract class Canine extends Animal {public void roam() {// TODO:}
}
如果尝试创建 Canine 的实例对象,编译器不会通过:
虽然无法创建 Canine 的实例对象,但作为一种父类型,依然可以被引用,可以作为多态参数,可以返回该类型。 所以,老白认为抽象类更偏向于统一行为,提供一个共同遵守的协议。
抽象方法
类可以是抽象的,方法也可以是抽象的,只不过抽象方法没有方法体。 定义抽象方法与抽象类类似:
public abstract makeNoise(); // {};
看到了吗? 抽象方法使用 abstract
声明,并且没有方法体。 可能有同学会问,抽象方法连方法体都没有那有啥用? 其实,这么做就是为了统一行为,强制子类必须自己实现这个抽象方法。
请记住,第一个具体类(非抽象类)必须实现所有「尚未实现」的抽象方法。 「尚未实现」的意思是,如果其上还有不止一个抽象父类,无论是谁如果实现了这个抽象方法,那第一个具体类可以不必再次实现,当然还是可以覆盖掉该方法。 举个例子也许会更清楚:
假如,Animal 和 Canine 都是抽象类,Animal 有一个抽象方法 makeNoise()
,Canine 也有一个抽象方法 roam()
,因为 Wolf 是第一个具体类,所以必须实现父类所有「尚未实现」的方法,即 makeNoise()
和 roam()
方法。 可是如果 Canine 实现了它的父类 Animal 的抽象方法 makeNoise()
,则 Wolf 就没有必要再次实现 makeNoise()
方法,但还是可以覆盖的。
有点绕,是吗? 实现抽象方法有点像前面学过的方法覆盖,只不过覆盖是可选择的,实现抽象方法是强制的。
抽象类和抽象方法的使用规则
- 抽象类只能被继承,不能被实例化;
- 抽象类允许同时存在具体方法和抽象方法;
- 如果某个类中存在抽象方法,那么这个类就必须声明为抽象类;
- 第一个具体类必须实现所有「尚未实现」的抽象方法。
《 上一篇 神奇的「多态」 | 下一篇 对象的起源 Object 》 |
---|