今天继续填坑,说一下Java多态。
上一篇博客中,我们已经学习了继承,这里我补充一个小的知识点。其实任何一个我们定义的类,假如没有给这个类继承一个父类,那么这个类就默认继承一个Object类。
我们先来看一下多态的定义吧
简单来说就是子类重写了父类的重名方法,当我们调用这个方法是可以调用到不同类中的同名方法。我们先来看个例子吧
public class PolyDemo {
public static void main(String[] args) {
print(new Object());
print(new Person());
print(new Student());
print(new GraduateStudent());
}
public static void print(Object o){
System.out.println(o.toString());
}
}
class Person{
public String toString(){
return "Person!";
}
}
class Student extends Person{
public String toString(){
return "Student!";
}
}
class GraduateStundet extend Student{
public String toString(){
return "GraduateStudent!";
}
}
在这段代码中,我定义了三个类,分别是Person,Student和GraduatStudent。三个类是继承关系。可以看到三个类中都有一个重名的方法:toString。我们构建一个函数print来调用这个toString方法。
这里我来解释一下为什么要把print的形参设成Object类型。这里就涉及到一个重要的知识点:动态绑定。什么叫动态绑定呢?我们先来看一下这几个类的继承关系:
Object <- Person <- Student <- GraduateStudent
在这关系中,GrandeStudent是最特别的类,Object是最通用的类。在我们调用print方法时候,其实计算机会先从最特殊的类出发(GraduateStudent),如果我们传入的参数是对应的GrandeStudent类,那么就在这个类中调用toString方法。但假如我们的参数不是GrandeStudent呢?那Java虚拟机就会自动向上转型,查找GrandeStudent的父类,看看形参与参数是否匹配,若匹配,则调用该类的toString方法。
那问题来了,假如找不到参数对应类中的方法呢?我把GraduateStudent的toString方法注释了
class GraduateStundet extend Student{
}
大家可以猜一下运行的结果。我这里就直接给大家放出运行结果吧:
可以看到,由于GraduateStudent中没有toString的方法,那么就会调用上一级,也就是它的父类中看看是否有重名的toString方法。如果有就直接调用,直到最终的父类Object。这里我们简单一点记忆就是从特殊到普遍,从儿子到老子。
为了加深大家的理解,我这里给出一道题目,设置一个printArea的方法,来打印所有几何体的面积。几何体和圆的类代码我已经在上一篇博客中给出了,我现在再给出长方形类的代码。
class Rectangle extends GeometicObject{
double length,width;
public Rectangle(){
this.length = 2.0;
this.width = 1.0;
}
public Rectangle(double length , double width,String color, boolean filled){
super(color,filled);
this.length = length;
this.width = width;
}
public double getArea(){
return width * length;
}
public String toString(){
return super.toString() + "\nRectangle 's length :" + length
+ "\nRectangle 's width :" + width;
}
}
接下来我们来构造一个printArea的方法:
public static void printArea(Geometry o){
System.out.println("面积为:" + o.getArea());
}
值得注意,为什么这里不用Object o作为形参呢?这是因为我们计算面积,面向的对象应该是所有的几何体,因而以几何体作为最终父类更为合适。
今天的多态内容到这里就结束了,其实多态跟继承一样,并不难,关键在于灵活运用,分析好类之间的关系,合理进行继承和方法重写!