物件導向程式語言Java 簡介 1
內容大綱 導論 物件與類別 封裝 繼承 同名異式 結論 2
導論 Java語言是美國昇陽電腦公司(Sun Micro System) 所發展出的一程式語言。 Java是一物件導向(Object-Oriented)程式語言: 物件導向是近年來資訊界廣為使用的觀念及技術。 物件導向有許多良好的特性,例如: 封裝性可以使物件的介面定義明確。 繼承性可以增加軟體的可再用性、有助於分類及模板設計等。 3
導論(c.2) 在制定Java時的原則: 使用者不必接受艱深的訓練,就可以開始設計程式。 無程式設計經驗的人可以減少艱深的學習。 儘可能與在當時許多程式設計師都採用的C及C++語言相似。 已有C或C++程式設計的人也能很快的具有以Java設計程式的能力。 刪除了C及C++許多極少使用、不容易理解或常被混淆的功能。 4
物件與類別 在物件導向的程式語言中,類別是一個不可或缺的機制,它擔負著架構物件的重責大任,它的主要用途是在規劃物件的內部構造,表示物件與物件間的關係,聯絡管道及運作方式。 物件是以類別來建立的。也就是說,類別定義了物件的架構,然後系統才能根據類別中所定義的架構產生實際物件。 5
物件與類別(c.2) 物件導向程式都是以類別為基本單位所組成的。 物件導向程式在執行時的主體是物件,而非類別。 6
物件與類別(c.3) class C { int i; } class D { public static void main(String[] args) { C c1; // 宣告一個物件 c1 c1 = new C(); // 產生一個物件 c1 7
物件與類別(c.4) // 之後的文字代表程式的註解。 int i C c1; c1 = new C(); 註:資料型態包含int, float, double, char以及 boolean 等。 C c1; 類別 D 以類別 C 為範本,宣告了一個物件,它的名字為 c1。 c1 = new C(); 等號右邊,new C() 的意義是:以類別 C 為範本產生一個物件。 經過指定運算 (等號) 後,這個以類別 C 為範本所產生的新物件,它的名字就叫做 c1。 兩者可和寫為 C c1 = new C(); 8
物件與類別(c.5) 在 Java 中,使用物件中的變數和方法方式是: 物件名稱.變數名稱 物件名稱.方法名稱 9
物件與類別(c.5) 輸出結果: c1.i = 10 c1.i = 20 class C { int i; } class D { public static void main(String[] args) { C c1 = new C(); c1.i = 10; System.out.println("c1.i = "+c1.i); c1.i = 20; 輸出結果: c1.i = 10 c1.i = 20 10
物件與類別(c.6) 執行結果: Joe has 300 dollars. Wason has 500 dollars. class Account { private int balance; //宣告一帳戶餘額 void clearAccount() { balance = 0; } //清空帳戶餘額的 "方法" void deposit(int m) { balance = balance + m; } // 存錢的 "方法" int getBalance() { return balance; } // 顯示目前餘額的 "方法" } class E { public static void main(String[] args) { Account joe = new Account(); // 產生一個帳戶:joe Account wason = new Account(); // 產生一個帳戶:wason joe.clearAccount(); // 將 Joe 的帳戶餘額清空 wason.clearAccount(); // 將 Wason 的帳戶餘額清空 joe.deposit(300); // Joe 存了 300 元 wason.deposit(500); // Wason 存了 500 元 System.out.println("Joe has " + joe.getBalance() + "dollars."); // 顯示 Joe 目前的帳戶餘額 System.out.println("Wason has " + wason.getBalance() + "dollars."); // 顯示 Wason 目前的帳戶餘額 執行結果: Joe has 300 dollars. Wason has 500 dollars. 11
封裝 將資料及使用此資料的所有方法包裝成一個物件,謂之。 封裝之特性使物件導向的系統較容易維護。 Java的封裝是將物件中資源(資料或方法)的存取分為幾個等級,以便來管理如何將物件中某些資源隱藏在物件中,某些資源應該開放給外界使用。 12
封裝(c.2) 資源(資料或方法)的存取分為四個等級: Public (公開) Private (私有) Protected (保護) 將物件內部的資源開放給外界使用。 Private (私有) 資源的所有權已完全屬於該類別所有,只有在物件內部才可對其作存取動作。任何外部的存取均會導致錯誤發生。 Protected (保護) 在所屬的 package 中是被視為 public 資源;但是在其他的 package 中,則只被繼承的子類別使用。 13
封裝(c.3) Default Access (預設存取) 在所屬的 package 中是被視為 public 資源;但是在其他的 package 中,則會被視為是 private 資源而無法被使用。 14
封裝(c.4) class C { private int i; // 私有資料 public int j; // 公開資料 int k; // 預設存取資料 } class D { public static void main(String[] args) { C c = new C(); c.i = 5; // Error! c.i 是 private資料,禁止存取! c.j = 10; // OK! c.k = 15; // OK! 15
封裝(c.5) class Account { private int balance; // 私有資料 void public clearAccount() { balance = 0; } // 公開方法 void deposit(int m) { balance = balance + m; } // 預設存取方法 int private getBalance() { return balance; } // 私有方法 } class D { public static void main(String[] args) { Account joe = new Account(); Account wason = new Account(); joe.clearAccount(); // OK! wason.clearAccount(); // OK! joe.deposit(300); // OK! wason.deposit(500); // OK! System.out.println(“Joe has ” + joe.getBalance() + “dollars.”); // ERROR! 使用私有方法 System.out.println(“Wason has ” + wason.getBalance() + “dollars.”); // ERROR! 使用私有方法 16
封裝(c.6) 封裝所形成的物件,其結構可分為兩部分: 介面(Interface):定義與物件互動的方式。 實作(Implementation):定義物件行為。 上例中 class Account { private int balance; void public clearAccount() { balance = 0; } void deposit(int m) { balance = balance + m; } int private getBalance() { return balance; } } 17
封裝(c.7) 物件間靠著訊息傳遞互通有無,彼此合作。所以,物件可接收訊息也可發送訊息。 上例中 class D { … joe.clearAccount(); // 送訊息 clearAccount() 給物件 joe wason.clearAccount(); // 送訊息 clearAccount() 給物件 wason joe.deposit(300); // 送訊息 deposit(300) 給物件 joe wason.deposit(500); // 送訊息 deposit(500) 給物件 wason } 18
繼承 繼承是類別間之關係,在此關係中某類別之資料結構與行為可供其關係中之類別分享。 繼承者稱為子類別(Subclass),被繼承者稱為父類別(Superclass)。 Java使用extends來表示繼承的關係。 19
繼承(c.2) 下例中,類別 D繼承類別 C: class C { ... } class D extends C { 當類別 D 繼承了類別 C 後,類別 C 中一切可以被繼承的事物 (包括所有的 非 private 的資源) 都將變成類別 D 中的一部分。 20
繼承(c.3) class C { private int i; public void setInfo(int x) { i = x; } public int getInfo() { return i; } } class D extends C {} // 類別 D 繼承類別 C class E extends C {} // 類別 E 繼承類別 C class F { public static void main(String[] args) { D d = new D(); E e = new E(); d.setInfo(5); e.setInfo(7); System.out.println("The value of d is "+d.getInfo()); System.out.println("The value of e is "+e.getInfo()); 執行結果: The value of d is 5 The value of e is 7 21
繼承(c.4) 子類別將由父類別繼承來的屬性(變數、資料結構)或方法(行為)重新定義的動作稱為覆寫(overriding)。 方法覆寫 將繼承自父類別的方法遮蓋起來,使得以子類別所產生的物件不能再使用已經被覆蓋的方法。 這種設計主要是使我們在繼承類別時,可以將不符合需求的方法加以改寫,如此一來,子類別的使用者就不會也不能看到及使用父類別中的方法,達到重新設計的目的。 變數覆寫 將繼承自父類別的變數遮蓋起來。事實上,當變數產生覆蓋問題時,在父類別中的變數宣告並不會因此而消失,它只是隱藏起來而已。 22
繼承(c.5) 變數覆寫 class C { int i = 10; } class D extends C { int i = 5; class E { public static void main(String[] args) { D d = new D(); System.out.println("d = "+d.i); 執行結果: d = 5 23
繼承(c.6) 方法覆寫 class C { void f(String s) { System.out.println("f in class C: "+s); } class D extends C { System.out.println("f in class D: "+s); // 父類別中的方法 f將被此方法覆寫! class E { public static void main(String[] args) { D d = new D(); d.f("hello"); 輸出結果: f in class D: hello 24
同名異式 簡稱為多型。 指的是一個方法可以有許多型式,也就是,相同的方法名稱,定義以不同的實作(implementation)。 多型的目的是希望簡化系統發展的複雜性並增加其彈性。 25
同名異式(c.2) 多型在程式執行時,呼叫一方法是以動態連結(Dynamic Binding)的方式,判斷當時被呼叫物件所屬的類別來決定執行那一實作,所以又稱為動態多型。 動態多型是建立在繼承的架構上。 26
同名異式(c.3) 執行結果: Triangle! Rectangle! Circle! abstract class Shape { public abstract void f(); } class Triangle extends Shape { public void f() { System.out.println("Triangle!"); class Rectangle extends Shape { System.out.println("Rectangle!"); class Circle extends Shape { System.out.println("Circle!"); class E { public static void main (String[] args) { Shape[] s = new Shape[] { new Triangle(), new Rectangle(), new Circle() }; for (int i=0; i<s.length; i++) { s[i].f(); } 執行結果: Triangle! Rectangle! Circle! 27
同名異式(c.4) 當呼叫一方法時,決定執行那個實作,是依參數的數目與類型來做決定,此稱為多重定義、過荷或超載(Overloading)。 過荷又稱為靜態多型。 因此,在設計方法過荷時需要特別小心,千萬不能有任何方法的參數個數及型態是完全一致的。 28
同名異式(c.5) 例如: int add(int i, int j) { return i + j; } float add(float i, float j) { return i + j; } double add(double i, double j) { return i + j; } int add(int i, float f) { return i + (int) f; } int add(int i, int j, int k) { return i + j + k; } add(1, 2) add(1, 2, 3) 29
結論 本單元只介紹了Java有關於物件導向的特性: 有興趣學好Java者應選修該門課程或買書自修,並多作練習。 物件 類別 封裝 繼承 同名異式 有興趣學好Java者應選修該門課程或買書自修,並多作練習。 30