现在,让我们回到“乐器”(instrument)示例。由于有多态机制,我们可根据自己的需求对系统添加任意多的新类型,而不需要更改tune()方法。在一个设计良好的oop程序中,大多数或者所有方法都会遵循tune()的模型,而且只与基类接口通信。这样的程序是可扩展性的,因为可以从通用的基类继承出新的数据类型,从而新添加一些功能。那么操作基类的接口的方法不需要任何改动就可以应用于新类。
考虑一下“乐器”的例子,如果我们向基类中添加了更多的方法,并加入一些新类,将会出现什么情况?请看下图:
事实上,不需要修改tune()方法,所有的新类都能与原有类一起正确运行。即使tune()方法是单独存放在某个文件中,并且在Instrument接口中添加了其他的方法,tune()方法也不要在编译就可以正确地运行。下面是具体的实现:
package polymorphism.music3;
//:polymorphism/music3/Note.java
//Notes to play on musical instruments.
public enum Note {
MIDDLE_C,C_SHARP,B_FLAT;//ect
}
package polymorphism.music3;
//polymorphism/music3/Music3.java
//An extensible program
import static net.mindview.util.Print.*;
class Instrument {
public void play(Note n){
print("Instrument.play() "+n);
}
public String what(){
return "Instrument";
}
public void adjust(){
print("Adjusting Instrument");
}
}
class Wind extends Instrument{
public void play(Note n){
print("Wind.play() "+n);
}
public String what(){
return "Wind";
}
public void adjust(){
print("Adjusting Wind");
}
}
class Percussion extends Instrument{
public void play(Note n){
print("Percussion.play() "+n);
}
public String what(){
return "Percussion";
}
public void adjust(){
print("Adjusting percussion");
}
}
class Stringed extends Instrument{
public void play(Note n){
print("Stringed.play() "+n);
}
public String what(){
return "Stringed";
}
public void adjust(){
print("Adjusting Stringed");
}
}
class Brass extends Wind{
public void play(Note n){
print("Brass.play() "+n);
}
public void adjust(){
print("Adjusting Brass");
}
}
class Woodwind extends Wind{
public void play(Note n){
print("Woodwind.play() "+n);
}
public void adjust(){
print("Adjusting Woodwind");
}
}
public class Music3 {
//Don't care about tpye ,so new types
//added to the system still work right:
public static void tune(Instrument i){
//...
i.play(Note.MIDDLE_C);
}
public static void tuneAll(Instrument[] e){
for(Instrument i:e){
tune(i);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
//Upcasting during addition to the array:
Instrument[] orchestra ={
new Wind(),
new Percussion(),
new Stringed(),
new Brass(),
new Woodwind()
};
tuneAll(orchestra);
}
}
///:~
输出结果:
/*
*
* Wind.play() MIDDLE_C
* Percussion.play() MIDDLE_C
* Stringed.play() MIDDLE_C
* Brass.play() MIDDLE_C
* Woodwind.play() MIDDLE_C
*
*/
分析:
新添加的方法what()返回一个带有类描述的String引用,另一个新添加的方法adjust()则提供每种乐器的调音方法。
在main()方法中,当我们将某种引用置入orchestra数组中,就会自动向上转型到Instrument。可以看到,tune()方法完全可忽略他周围代码所发生的全部变化,依旧正常运行。这正是我们期待多态所具有的特性。我们所做的代码修改,不会对程序中其他不应该受到影响的部分产生破坏。换句话说,多态是一项让程序员“将改变的事物与未变的事物分离开来”的重要技术。