如果子类的方法覆盖了父类的方法,我们也说父类的那个方法在子类有了新的版本或者新的实现。覆盖的新版本具有与老版本相同的方法签名:相同的方法名称和参数表。因此,对于外界来说,子类并没有增加新的方法,仍然是在父类中定义过的那个方法。不同的是,这是一个新版本,所以通过子类的对象调用这个方法,执行的是子类自己的方法。
覆盖关系并不说明父类中的方法已经不存在了,而是当通过一个子类的对象调用这个方法时,子类中的方法取代了父类的方法,父类的这个方法被“覆盖”起来而看不见了。而当通过父类的对象调用这个方法时,实际上执行的仍然是父类中的这个方法。注意我们这里说的是对象而不是变量,因为一个类型为父类的变量有可能实际指向的是一个子类的对象。
当调用一个方法时,究竟应该调用哪个方法,这件事情叫做绑定。绑定表明了调用一个方法的时候,我们使用的是哪个方法。绑定有两种:一种是早绑定,又称静态绑定,这种绑定在编译的时候就确定了;另一种是晚绑定,即动态绑定。动态绑定在运行的时候根据变量当时实际所指的对象的类型动态决定调用的方法。Java缺省使用动态绑定。
举一个例子:
public class Figure {
double a;
double b;
public Figure( double a,double b) {
this.a=a;
this.b=b;
}
public double area() {
System.out.println("父类中计算面积的方法无实际意义,需要在子类中重写");
return 0;
}
}
```java
public class Rectangle extends Figure {
public Rectangle(double a,double b) {
super(a,b);
}
public double area() {
System.out.println("长方形的面积为:");
return super.a*super.b;
}
}
```java
public class Triangle extends Figure {
public Triangle(double a,double b) {
super(a,b);
}
public double area() {
System.out.println("三角形的面积为:");
return (super.a*super.b)/2;
}
}
public class TEST {
public static void main(String[] args) {
Figure figure=new Rectangle(9,9);
System.out.println(figure.area());
Figure figure1=new Triangle(6,8);
System.out.println(figure1.area());
Figure figure2=new Figure(8,8);
System.out.println(figure2.area());
}
}