使用过面向对象编程(OPP)的都知道,多态是OPP的一个主要特性之一。Java做为一种OPP语言,其也有多态特性。
那么什么是多态呢?
指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
先举个例子,我们定义Shape类,Square和Circle继承Shape类,并重载其draw方法。
public class Shape {
public void draw() {
System.out.println("draw in Shape!");
}
}
class Square extends Shape {
public void draw() {
System.out.println("draw in Square!");
}
}
class Circle extends Shape {
public void draw() {
System.out.println("drwa in Circle!");
}
}
测试代码如下,
public static void main(String[] args) {
Shape square = new Square();
square.draw();
Shape circle = new Circle();
circle.draw();
}
测试结果为,
draw in Square!
drwa in Circle!
以上代码就涉及到多态现象。当我们调用draw方法时,Java会根据运行时对象的类型来判断调用谁的方法。比如square在运行时是Square类型,就会调用其draw方法;circle也类似。
或许你会疑问,square的类型命名是Shape,为什么能赋值为Square类型的呢。这就是向上转型了。
继承最重要的不是给子类提供了方法,而是父类与子类的关系。该关系可以概括为子类是父类的一种(The new class is a type of the existing class)。
由于继承意味着,父类的方法,在子类中也存在,所以向父类发送的消息(父类的方法调用),也可以发送给子类。
这样我们可以理解,Shape square = new Square();该语句为什么可以通过编译。
另外,向上转型是安全的,这是由于,向上转型是由特定的类转为一般的类。也就是,子类是父类的超级(superset),子类包含所有父类的方法。
上面提到Java会根据运行时对象的类型来判断调用的方法,这就是后链接。与链接接相对的是,前链接。
将方法与方法的对象联系起来叫链接。在程序执行前完成链接的(由编译器或链接器完成),叫前链接,C语言就是一个例子。
然而,Java中,由于多态,在编译的时候,编译器仅仅知道一个引用,无法知道调用哪个方法。后链接解决了该问题,在运行时根据对象的类型来链接方法。后链接也称为动态链接(dynamic binding)、运行时链接(run-time binding)。
Java中,所有的方法都是后链接,除非,该方法声明为final方法。很容易理解,因为final方法无法被重写,所以编译器可以知道该方法属于哪个类型。