程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 為什麼要上溯造型

為什麼要上溯造型

編輯:關於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添加一個新類型,仍然需要進行大量編碼工作。此外,即使忘記對自己的某個方法進行過載設置,編譯器也不會提示任何錯誤。這樣一來,類型的整個操作過程就顯得極難管理,有失控的危險。
但假如只寫一個方法,將基礎類作為自變量或參數使用,而不是使用那些特定的衍生類,豈不是會簡單得多?也就是說,如果我們能不顧衍生類,只讓自己的代碼與基礎類打交道,那麼省下的工作量將是難以估計的。
這正是“多形性”大顯身手的地方。然而,大多數程序員(特別是有程序化編程背景的)對於多形性的工作原理仍然顯得有些生疏。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved