这个措施看起来也许显得有些奇怪。为什么所有人都应该有意健忘一个工具的范例呢?举办上溯造型时,就大概发生这方面的迷惑。并且假如让tune()简朴地取得一个Wind句柄,将其作为本身的自变量利用,好像会越发简朴、直观得多。但要留意:如果那样做,就需为系统内Instrument的每种范例写一个全新的tune()。假设凭据前面的推论,插手Stringed(弦乐)和Brass(铜管)这两种Instrument(乐器):
//: Music2.java // Overloading instead of upcasting class Note2 { private int value; private Note2(int val) { value = val; } public static final Note2 middleC = new Note2(0), cSharp = new Note2(1), cFlat = new Note2(2); } // Etc. class Instrument2 { public void play(Note2 n) { System.out.println("Instrument2.play()"); } } class Wind2 extends Instrument2 { public void play(Note2 n) { System.out.println("Wind2.play()"); } } class Stringed2 extends Instrument2 { public void play(Note2 n) { System.out.println("Stringed2.play()"); } } class Brass2 extends Instrument2 { public void play(Note2 n) { System.out.println("Brass2.play()"); } } public class Music2 { public static void tune(Wind2 i) { i.play(Note2.middleC); } public static void tune(Stringed2 i) { i.play(Note2.middleC); } public static void tune(Brass2 i) { i.play(Note2.middleC); } public static void main(String[] args) { Wind2 flute = new Wind2(); Stringed2 violin = new Stringed2(); Brass2 frenchHorn = new Brass2(); tune(flute); // No upcasting tune(violin); tune(frenchHorn); } } ///:~
这样做虽然行得通,但却存在一个极大的漏洞:必需为每种新增的Instrument2类编写与类细密相关的要领。这意味着第一次就要求多得多的编程量。今后,如果想添加一个象tune()那样的新要领可能为Instrument添加一个新范例,仍然需要举办大量编码事情。另外,纵然健忘对本身的某个要领举办过载配置,编译器也不会提示任何错误。这样一来,范例的整个操纵进程就显得极难打点,有失控的危险。
但如果只写一个要领,将基本类作为自变量或参数利用,而不是利用那些特定的衍生类,岂不是会简朴得多?也就是说,假如我们能掉臂衍生类,只让本身的代码与基本类打交道,那么省下的事情量将是难以预计的。
这正是“多形性”大显身手的处所。然而,大大都措施员(出格是有措施化编程配景的)对付多形性的事情道理仍然显得有些陌生。