考虑这样一个问题:
有三个类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()方法。