服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

为什么要上溯造型


  这个程序看起来也许显得有些奇怪。为什么所有人都应该有意忘记一个对象的类型呢?进行上溯造型时,就可能产生这方面的疑惑。而且如果让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添加一个新类型,仍然需要进行大量编码工作。此外,即使忘记对自己的某个方法进行过载设置,编译器也不会提示任何错误。这样一来,类型的整个操作过程就显得极难管理,有失控的危险。
  
  但假如只写一个方法,将基础类作为自变量或参数使用,而不是使用那些特定的衍生类,岂不是会简单得多?也就是说,如果我们能不顾衍生类,只让自己的代码与基础类打交道,那么省下的工作量将是难以估计的。
  
  这正是“多形性”大显身手的地方。然而,大多数程序员(特别是有程序化编程背景的)对于多形性的工作原理仍然显得有些生疏。

扫描关注微信公众号