Java中的多态:动态绑定

考虑这样一个问题:
有三个类Unicycle、Bicycle和Tricycle。
它们都继承自Cycle类。
父类Cycle有它的ride()方法,而它的三个子类也各自都有自己对于ride()方法的实现。
现在有这样一样个方法test(), 它接收一个Cycle类作为参数。
即test (Cycle c)。
如果想要实现将Cycle的三个子类分别传入,然后程序会根据传入的类的不同来实现不同的ride()方法。
应该怎样做呢?

比较直观的方法如下:

class Unicycle extends Cycle{
    //独轮车的id是1
    private int id;
    //带一个参数的构造器
    public Unicycle(int id){
        this.id = id;
    }
    public int getId(){
        return id;
    }
}
class Bicycle extends Cycle{
    private int id;
    public Bicycle(int id){
        this.id = id;
}
public int getId(){
        return id;
    }
}
class Tricycle extends Cycle{
    private int id;
    public Tricycle(int id){
        this.id = id;
}
public int getId(){
        return id;
    }
}


public class Cycle{
    public static void test (Cycle c,int id){
        switch (id){
            case 1:
            System.out.println("riding Unicycle");
            break;
            case 2:
            System.out.println("riding Bicycle");
            break;
            case 3:
            System.out.println("riding Tricycle");
            break;
        }
    }
    public static void main(String[] args) {
            //生成新的子类对象
            Unicycle uni = new Unicycle(1);
            Bicycle bic = new  Bicycle(2);
            Tricycle tri = new Tricycle(3);
            //自动向上转型,所以uni,bic,tri这三个对象都可以作为Cycle对象传入
            Cycle.test(uni,uni.getId());
            Cycle.test(bic,bic.getId());
            Cycle.test(tri,tri.getId());

    }
}

output:

riding Unicycle
riding Bicycle
riding Tricycle

此方法的逻辑就是,为每一类Cycle的子类分别赋一个id值,然后在test()方法中加入判断语句,以此来帮助程序判断该实现哪一个方法。
可是真的需要这么麻烦吗?
试想一下,现在Cycle只有3个子类,可是如果有30个子类呢?
是不是也要一个一个地编号再加入相应的判断语句呢?
如果程序后来需要修改呢?

可想而知,这样的方法是行不通的。
那么应该怎样做呢?

java为我们提供了动态绑定机制。

试看如下代码:

class Unicycle extends Cycle{
    public void ride(){
        System.out.println("riding Unicycle");
    }
}

class Bicycle extends Cycle{
    public void ride(){
        System.out.println("riding Bicycle");
    }
}

class Tricycle extends Cycle{
    public void ride(){
        System.out.println("riding Tricycle");
    }
}
//父类Cycle类
public class Cycle{
    public void ride(){
        System.out.println("base class riding");
    }
//设计一个go()方法用来控制Cycle动起来
    public static void go (Cycle c){
        c.ride();
    }
    public static void main(String[] args) {
        System.out.println("输出结果:");
        Unicycle uni = new Unicycle();
        go(uni);
        go(new Bicycle());
        go(new Tricycle());
        System.out.println("------------");

    }
}

output:

输出结果:
riding Unicycle
riding Bicycle
riding Tricycle
------------

从结果可以看出,在动态绑定机制的帮助下

程序只需要和父类打交道。

父类Cycle有ride()方法,而其子类则都重写了父类的ride()方法。
所有的子类都被视作Cycle类,
因此它们的对象都可以被当做参数传入go()方法中。
也就是说,每一个子类的都被当做父类来处理,
只不过是一种特殊的父类(因为存在继承关系)。
而系统则自动地动态地实现与传入的对象相匹配的方法。
如此一来,当存在很多个子类时,
只需要继承Cycle类,并重载父类的方法即可。

另外需要注意的是:

如果父类中存在一个方法如stand(),而子类中只有Unicycle类重载了父类的stand()方法,结果会怎样呢?
试看如下代码:

//...
//Unicycle重写父类的stand()方法
    public void stand (){
        System.out.println("Unicycle standing");
    }
//...
//父类的stand()方法
    public void stand (){
        System.out.println("base class standing");
    }
        //...
        Cycle uni2 = new Unicycle();
        uni2.stand(); 
        new Unicycle().stand();
        new Bicycle().stand();
        new Cycle().stand();

output:

Unicycle standing
Unicycle standing
base class standing
base class standing

从输出可知:

当子类重写了父类的方法时,
即使从Cycle uni2 = new Unicycle();这一语句来看,
uni2对象的引用似乎是指向Cycle类的,
其结果依然是调用子类的stand()方法。

而其他没有重写父类stand()方法的子类如果调用父类的stand()方法,
则就相当于是父类调用了stand()方法。

猜你喜欢

转载自blog.csdn.net/qq_23889793/article/details/74762431