前面学习了Java面向对象的继承机制,下面来学习Java的多态机制。
还记得在校期间上《大学物理》课的时候,老师在讲物质之间的万有引力定律,其实我内心不是很理解,就感觉有点点抽象,在生活中没有实际应用。
换句话说,我们看不见,摸不着,但不能否认他的存在。
又比如说,水果就是一个抽象概念。
“吃水果”,代表吃苹果香蕉梨等具体的水果,而不是“水果”这个物质。
在Java面向对象编程中,也有“抽象”这一个概念,Java提供了abstract关键字。

abstract是Java语言中一个重要的关键字,是表示抽象的修饰符,可以修饰类和方法,被修饰的类和方法分别被称为抽象类和抽象方法。
比如水果类就是一个抽象类,具体到某种水果的实现时,总是归类于某类水果种类。
所以说,在需要某个抽象类的具体实例化时,只能用具体类的实例来代替。
而且,抽象类不能实例化,不能new一个新对象。
在Java中,抽象类可以理解为一个半成品,需要子类继承该抽象类,并且覆盖抽象方法,这样子类才有new对象的能力。
但如果子类还是没能实现父类的抽象方法,那么子类也是抽象类,可以无限循环下去。
抽象类一般位于抽象层,表示该类的设计还没完善,还没得到具体解释,必须在子类进一步完善之后,才可以实例化对象。
创建一个抽象类:User
package cn.zwz;
public interface User {
void say();
}创建User类的实例化:Student
package cn.zwz;
public class Student implements User{
@Override
public void say() {
System.out.println("我是学生");
}
}Student类实现了抽象类User的say方法,才能实例化对象进行调用方法:
package cn.zwz;
public class Main {
public static void main(String[] args) {
Student student = new Student();
student.say();
}
}Java的abstract有一定的约束条件,比如:
1.抽象类可以没有抽象方法,如:
public abstract class User {
}2.在一个类中存在抽象方法时,该类会变成抽象类
public abstract class User {
abstract void say();
}3.类的构造方法不能抽象化
public abstract class User {
private String name;
private int age;
// 错误
abstract public User(String name, int age) {
this.name = name;
this.age = age;
}
}4.类的静态方法不能抽象化
public abstract class User {
/**
* 错误
*/
public abstract static int add(int a,int b) {
return a + b;
}
}5.抽象类抽象方法不能被final修饰
public abstract class User {
private String name;
private final int age; // 错误
}6.抽象方法不能和public等权限关键字连用。
public abstract class User {
private String name;
private abstract int age; // 错误
}在Java程序设计中,不支持多继承,但支持实现多个接口。
Java提供了interface关键字来定义接口,可以理解为是一种规范或者一种标准。
Java采用单一继承机制,多继承的使用场景则用接口来弥补。
比如有一名工人张三,在人类生物学角度看,只有一位生物学意义上的父亲。但对张三来说,在不同场景下有不同的身份,在学校是一个学生,在公司是一名软件工程师,在超市是一名消费者…根据传统的面向对象概念,张三必须要有学生父亲,才能成为学生;必须要有一名消费者父亲,才能成为消费者…这显然是不成立的。
Java如何实现?就是用了接口的概念,张三接了学生的口,那么他就是学生,接了消费者的口,那么他就是消费者。
又比如说生活中各式各样的标准件,比如A4纸,无需提供纸张的长宽度,即可完成打印;比如电器的220V电压,无需提供电阻和电流值;又比如说软考,我们通过学习成长,拿到了软考证书,就可以去当软件工程师。
接口就是规范、标准,在日常生活中有着各式各样广泛的应用。在Java开发中也是这样,开发者在设计接口时,可以不关注细节,只关心接口的功能和数据格式要求。
比如下面的一个User接口
public interface User {
/**
* 要实现说话功能
*/
public void say();
/**
* 要实现加法计算功能
* @param x
* @param y
* @return
*/
public int add(int x,int y);
}在Java程序设计中,接口的出现让面向对象程序设计理念前进了一大步,使得代码能够更好的模拟现有世界。

在Java中,一个类可以通过关键字 implements 申明自己实现的接口。
如果需要实现多个接口,用逗号隔开即可。
如下Student学生类实现了User接口。
public class Student implements User{
@Override
public void say() {
System.out.println("我是一名学生!");
}
@Override
public int add(int x, int y) {
return x + y;
}
}Student类实现了User接口,和继承机制一样,继承了接口中定义的常量和抽象方法。
常量可以直接使用,但抽象方法需要在类中提供具体实现;也可以不实现且继续成为抽象类,不能实例化对象。
接口是抽象类的子集,是抽象类的一种特殊实现。
接口中所有方法都必须是抽象的,但抽象类中可以有不抽象的方法。
接口中方法默认为public、abstract,抽象类中默认为public、static、final,两者存在明显差异。
接口不能存在构造方法,而抽象类可以。
接口没有普通成员变量,但抽象类可以。
接口不能存在静态方法,但抽象类可以。
Java类可以实现多个接口,但只能继承一个抽象类。
从以上抽象类和接口的对比中可以发现,接口是在系统架构设计方面发挥更多的作用,主要用于定义模块之间的关联信息。而抽象类在实际编程中提供更好的作用,可以实现代码的复用,降低代码的耦合性。

多态是面向对象程序设计的一大特性,也是一个基本的设计原则。
对于同样一个触发条件,不同对象的响应事件是不一样的,也就是多态。
在生物学的多样性,也就是Java的多态机制。
Java可以通过方法重载、方法覆盖来实现多态机制,在不同的应用场景有着丰富的应用场景。