之前基于继承的多态,可以看出来父类并没有被实例化,而且成员方法也可以没有实体也就是函数体,只需要父类类型引用指向各个子类对象,通过子类方法的覆盖就可以达到调用方法的目的,回头看下之前的例子,父类Book有三种各异的方法,又是chinese,又是english和maths,如果从属性的角度考虑,这到底是本神马书?因此一般来说,这个父类用来被继承和产生多态,可以避免让它进行初始化,也就是没法new出来,既然没法实例化,就相当于标记成了一个抽象的类,无法创建任何类型的实例,但是却依旧可以创建抽象类类型的引用变量来进行多态调用
抽象类的标记十分简单,在声明前面加一个关键字abstrace即可,比如进行实例化编译就会报错
abstract class Book { void chinese() {}; } class ChineseBook extends Book { void chinese() { System.out.println("A chinese book"); } } public class Main { public static void main(String[] args) { Book book = new Book(); book.chinese(); } }
这里Book类进行抽象化,编译出错
javac Main.java Main.java:13: 错误: Book是抽象的; 无法实例化 Book book = new Book(); ^ 1 个错误
换成父类引用指向的子类对象初始化进行多态,即可
abstract class Book { void chinese() {}; } class ChineseBook extends Book { void chinese() { System.out.println("A chinese book"); } } public class Main { public static void main(String[] args) { Book book = new ChineseBook(); book.chinese(); } }
既然abstract的类,被抽象化,无法实例化,那这个类肯定被extends过;同样方法也可以添加关键字abstract来进行抽象化,但是要注意的是,如果声明了一个抽象的方法,就必须将其类也标记为抽象类,不能再非抽象类中定义抽象方法
抽象的方法定义
abstract class Book { abstract void chinese(); }
要注意的是抽象的方法不用带任何函数体,带了编译会报错
抽象方法的多态程序
abstract class Book { abstract void chinese(); } class ChineseBook extends Book { void chinese() { System.out.println("A chinese book"); } } public class Main { public static void main(String[] args) { Book book = new ChineseBook(); book.chinese(); } }
由此来看,并不影响子类覆盖方法的多态行为,下面再看一个
给父类加了一个正常的成员方法
abstract class Book { abstract void chinese(); void english() {}; } class ChineseBook extends Book { void chinese() { System.out.println("A chinese book"); } } public class Main { public static void main(String[] args) { Book book = new ChineseBook(); book.chinese(); } }
这里是没有问题的,子类的chinese()重写了父类对应的方法,最后book调用的方法还是执行的子类里的方法输出
假如这里将父类里的english方法改成抽象方法
abstract class Book { abstract void chinese(); abstract void english(); } class ChineseBook extends Book { void chinese() { System.out.println("A chinese book"); } } public class Main { public static void main(String[] args) { Book book = new ChineseBook(); book.chinese(); } }
编译就会出错
javac Main.java Main.java:6: 错误: ChineseBook不是抽象的, 并且未覆盖Book中的抽象方法english() class ChineseBook extends Book { ^ 1 个错误
可以看到错误信息居然是ChineseBook不是抽象类,理清一下脉络,english不是抽象方法,但ChineseBook继承了Book,于是也继承了Book的所有方法,而这里都是抽象方法,于是乎ChineseBook有了抽象成员方法,那么ChineseBook必须也声明为抽象类才行,这显然不满足后面的实例化要求,于是必须在子类里将english方法也进行覆盖即可
abstract class Book { abstract void chinese(); abstract void english(); } class ChineseBook extends Book { void chinese() { System.out.println("A chinese book"); } void english() { System.out.println("A english book"); } } public class Main { public static void main(String[] args) { Book book = new ChineseBook(); book.chinese(); } }
通过上面的几个例子,基本可以将抽象类和方法的要求理清了:
1:抽象类无法实例化,无法用new创建对象
2:抽象方法没有函数主体
3:抽象类里可以包括非抽象方法
4:只要类中有抽象方法,那么这个类必须声明为抽象类
5:抽象类的子类中必须覆盖掉父类所有的抽象方法