程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 在java中產生正確的行為

在java中產生正確的行為

編輯:關於JAVA

知道Java裡綁定的所有方法都通過後期綁定具有多形性以後,就可以相應地編寫自己的代碼,令其與基礎類溝通。此時,所有的衍生類都保證能用相同的代碼正常地工作。或者換用另一種方法,我們可以“將一條消息發給一個對象,讓對象自行判斷要做什麼事情。”

在面向對象的程序設計中,有一個經典的“形狀”例子。由於它很容易用可視化的形式表現出來,所以經常都用它說明問題。但很不幸的是,它可能誤導初學者認為OOP只是為圖形化編程設計的,這種認識當然是錯誤的。

形狀例子有一個基礎類,名為Shape;另外還有大量衍生類型:Circle(圓形),Square(方形),Triangle(三角形)等等。大家之所以喜歡這個例子,因為很容易理解“圓屬於形狀的一種類型”等概念。下面這幅繼承圖向我們展示了它們的關系:

上溯造型可用下面這個語句簡單地表現出來:

Shape s = new Circle();

在這裡,我們創建了Circle對象,並將結果句柄立即賦給一個Shape。這表面看起來似乎屬於錯誤操作(將一種類型分配給另一個),但實際是完全可行的——因為按照繼承關系,Circle屬於Shape的一種。因此編譯器認可上述語句,不會向我們提示一條出錯消息。
當我們調用其中一個基礎類方法時(已在衍生類裡覆蓋):
s.draw();
同樣地,大家也許認為會調用Shape的draw(),因為這畢竟是一個Shape句柄。那麼編譯器怎樣才能知道該做其他任何事情呢?但此時實際調用的是Circle.draw(),因為後期綁定已經介入(多形性)。
下面這個例子從一個稍微不同的角度說明了問題:
 

//: Shapes.java
// Polymorphism in Java

class Shape { 
  void draw() {}
  void erase() {} 
}

class Circle extends Shape {
  void draw() { 
    System.out.println("Circle.draw()"); 
  }
  void erase() { 
    System.out.println("Circle.erase()"); 
  }
}

class Square extends Shape {
  void draw() { 
    System.out.println("Square.draw()"); 
  }
  void erase() { 
    System.out.println("Square.erase()"); 
  }
}

class Triangle extends Shape {
  void draw() { 
    System.out.println("Triangle.draw()"); 
  }
  void erase() { 
    System.out.println("Triangle.erase()");
  }
}

public class Shapes {
  public static Shape randShape() {
    switch((int)(Math.random() * 3)) {
      default: // To quiet the compiler
      case 0: return new Circle();
      case 1: return new Square();
      case 2: return new Triangle();
    }
  }
  public static void main(String[] args) {
    Shape[] s = new Shape[9];
    // Fill up the array with shapes:
    for(int i = 0; i < s.length; i++)
      s[i] = randShape();
    // Make polymorphic method calls:
    for(int i = 0; i < s.length; i++)
      s[i].draw();
  }
} ///:~

針對從Shape衍生出來的所有東西,Shape建立了一個通用接口——也就是說,所有(幾何)形狀都可以描繪和刪除。衍生類覆蓋了這些定義,為每種特殊類型的幾何形狀都提供了獨一無二的行為。
在主類Shapes裡,包含了一個static方法,名為randShape()。它的作用是在每次調用它時為某個隨機選擇的Shape對象生成一個句柄。請注意上溯造型是在每個return語句裡發生的。這個語句取得指向一個Circle,Square或者Triangle的句柄,並將其作為返回類型Shape發給方法。所以無論什麼時候調用這個方法,就絕對沒機會了解它的具體類型到底是什麼,因為肯定會獲得一個單純的Shape句柄。
main()包含了Shape句柄的一個數組,其中的數據通過對randShape()的調用填入。在這個時候,我們知道自己擁有Shape,但不知除此之外任何具體的情況(編譯器同樣不知)。然而,當我們在這個數組裡步進,並為每個元素調用draw()的時候,與各類型有關的正確行為會魔術般地發生,就象下面這個輸出示例展示的那樣:
 

Circle.draw()
Triangle.draw()
Circle.draw()
Circle.draw()
Circle.draw()
Square.draw()
Triangle.draw()
Square.draw()
Square.draw()

當然,由於幾何形狀是每次隨機選擇的,所以每次運行都可能有不同的結果。之所以要突出形狀的隨機選擇,是為了讓大家深刻體會這一點:為了在編譯的時候發出正確的調用,編譯器毋需獲得任何特殊的情報。對draw()的所有調用都是通過動態綁定進行的。

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