多态复习笔记-1

再论向上转型

package java_test1;
/*
 * 2019/7/22
 * 多台测试向上转型
 * */
//创建一个乐谱枚举类型
enum Note{
	MIDDLE_C,C_SHARP,B_FLAT;
}
//创建一个instrument乐器类型
class instrument{
	public void play(Note n) {
		System.out.println("instrument.play()");
	}
}
//创建一个Wind管乐器类型,继承自instrument
//注意这里和instrument类型的play方法不同,她多输出了一个n
class Wind extends instrument{
	public void play(Note n) {
		System.out.println("Wind.play()"+n);
	}
}
public class Music {
	//演奏方法
	public static void tune(instrument i) {
		i.play(Note.MIDDLE_C);
	}
	public static void main(String[] args) {
		Wind w=new Wind();
		tune(w);
	}
}
//output:Wind.play()MIDDLE_C
  • music.tune()方法接受一个instrument引用,同时也接受任何导出自instrument的类。所以这里可以直接使用Wind的引用w作为参数给tune方法。
  • 这里值得注意的是,输出结果是Wind.play()MIDDLE_C而不是instrument.play(),说明执行的是Wind的play方法而不是instrument的。

忘记对象类型和转机

观察上面的代码,假如我们在tune方法参数列表变成Wind可能会很直观,但是如果这样,当我们需要添加其他乐器的时候,就必须为每一个乐器添加一个tune方法。如果我们仅仅写一个简单地方法,他接受基类作为参数,而不是那些特殊类的导出类,这样又会出现一个问题,如果使用向上转型的方式,编译器怎么知道我是哪一个具体导出类并且执行呢,这里就牵扯到了动态绑定。所以这里我们不需要去想他的具体实现过程,我们只需在基类的导出类中覆盖好对应方法,向上转型成基类,然后他就会自动实现对应类的方法

  • 动态绑定(又称后期绑定,运行时绑定。面向过程语言中使用的是前期绑定)编译器一直不知道对象的类型,但是方法调用机制能找到对应的方法体。