Chap 8 繼承 抽象類別與介面 8-1 類別的繼承 8-2 介面 8-3 介面的繼承 8-4 抽象類別 8-5 抽象類別與介面 8-6 常數類別
8-1 類別的繼承 8-1-1 類別架構 8-1-2 類別的繼承 8-1-3 覆寫和隱藏父類別的方法 8-1-4 隱藏父類別的成員變數 8-1-5 使用父類別的建構子
8-1-1 類別架構 - 繼承關係 類別的繼承關係可以讓我們建立類別架構, 在 UML 類別關聯性中, 繼承稱為一般關係 (Generalization) 例如 : 類別 Student 是繼承自類別 Person, 其類別架構如右圖所示 :
8-1-1 類別架構 - 建立類別架構 繼承不只可以多個子類別繼承同一個父類別, 還可以擁有很多層的繼承, 如下圖所示 :
8-1-2 類別的繼承 - 父類別 在 Java 宣告繼承的子類別前, 我們需要先有一個父類別來繼承 例如 : 父類別 Person 定義個人的基本資料, 類別宣告如下所示 : class Person { private int id; private String name; private double height; public void setid(int id) { public void setname(string n) { public void setheight(double h) { public void personinfo() {
8-1-2 類別的繼承 - 語法 Java 語言是使用 extends 關鍵字來宣告類別繼承存在的類別, 其宣告語法如下所示 : class 子類別名稱 extends 父類別名稱 { // 額外的成員變數和方法
8-1-2 類別的繼承 - 子類別 回到範例, 人們依據職業可以分成很多種類 : 學生 (Student) 老師 (Teacher) 和業務員 (Salesperson) 等, 以學生 Student 子類別的宣告為例, 其類別宣告如下所示 : class Student extends Person { private int grade; public Student(int id,string n,double h, int score) { public void studentinfo() {
8-1-2 類別的繼承 - 類別圖
8-1-2 類別的繼承 - 繼承的存取限制 子類別可以繼承父類別的所有成員變數和方法, 但是在存取時仍然有一些限制, 如下所示 : 子類別不能存取父類別宣告成 private 的成員變數和方法 父類別的建構子不屬於類別的成員, 所以子類別不能繼承父類別的建構子, 只能呼叫父類別的建構子, 詳見 < 第 8-1-5 節 : 使用父類別的建構子 >
8-1-3 覆寫和隱藏父類別的方法 - 說明 如果繼承的父類別方法不符合需求, 在子類別可以宣告同名 同參數列和傳回值的方法來取代父類別繼承的方法, 稱為 覆寫 (Override), 或稱為覆蓋 不過, 物件的實例方法並不能取代宣告成 static 的類別方法 如果父類別擁有類別方法, 在子類別需要宣告同樣的類別方法來取代它, 稱為 隱藏 (Hide)
8-1-3 覆寫和隱藏父類別的方法 - 差異 Java 語言覆寫和隱藏方法的差異, 如下表所示 : 父類別的實例方法 父類別的類別方法 子類別的實例方法覆寫編譯錯誤 子類別的類別方法編譯錯誤隱藏
8-1-3 覆寫和隱藏父類別的方法 - 範例 ( 父 ) 筆者準備修改上一節範例來說明覆寫和隱藏, 在父類別 Person 擁有類別方法和成員方法需要被子類別隱藏和覆寫, 類別宣告如下所示 : class Person { public static void printclassname() { public void personinfo() {
8-1-3 覆寫和隱藏父類別的方法 - 範例 ( 子 ) 子類別 Student 繼承自父類別 Person, 其類別宣告如下所示 : class Student extends Person { public static void printclassname() { public void personinfo() {
8-1-4 隱藏父類別的成員變數 - 說明 在子類別除了可以覆寫父類別的成員方法和隱藏類別方法外, 子類別也可以隱藏父類別的成員變數, 只需變數名稱相同, 就算變數的資料型態不同, 也一樣可以隱藏父類別的成員變數
8-1-4 隱藏父類別的成員變數 - 範例 父類別 Person 的成員變數 id 是宣告成 public 的整數, 如下所示 : class Person { public int id; Student 子類別是繼承自父類別 Person, 如下所示 : class Student extends Person { private String id;
8-1-5 使用父類別的建構子 - 說明 Java 子類別並不能繼承父類別的建構子, 只能使用 super 關鍵字呼叫父類別的建構子 ; 同理, 在子類別覆寫的方法和隱藏的成員變數, 也都可以使用 super 關鍵字來呼叫和存取
8-1-5 使用父類別的建構子 - 範例 ( 父 ) 例如 : 在 Person 父類別擁有建構子, 其類別宣告如下所示 : class Person { public static int count = 0; public int id; public String name; public Person(int id, String name) { public void personinfo() {
8-1-5 使用父類別的建構子 - 範例 ( 子 )1 Student 子類別是繼承自父類別 Person, 如下所示 : class Student extends Person { private String id; private String name; private int grade; public Student(int id,string n,string no,int grade) { super(id, n);
8-1-5 使用父類別的建構子 - 範例 ( 子 )2 public void personinfo() { super.personinfo(); System.out.println(" 姓名 ( 父 ): " + super.name); System.out.println(" 字號 ( 父 ): " + super.id);
8-2 介面 8-2-1 介面的基礎 8-2-2 介面的建立與使用 8-2-3 在類別實作多個介面
8-2-1 介面的基礎 - 說明 Java 介面 (Interface) 可以替類別的物件提供共同介面, 就算類別之間沒有任何關係 ( 有關係也可以 ), 一樣可以擁有共同的介面 如同網路通訊協定 (Protocol) 建立不同電腦網路系統之間的溝通管道, 不管 Windows 或 Unix 作業系統的電腦, 只要說 TCP/IP 就可以建立連線 換句話說, 介面是定義不同類別之間的一致行為, 也就是一些共同的方法
8-2-1 介面的基礎 - 範例 例如 :Car 和 CD 類別擁有共同方法 getprice() 取得價格,Java 程式碼可以將共同方法抽出成為介面 IPrice 如果 Book 類別也需要取得書價, 就可以直接實作 IPrice 介面, 表示可以取得物件價格, 這些類別都擁有相同行為 : 取得價格
8-2-2 介面的建立與使用 - 宣告語法 Java 介面和類別一樣都是參考資料型態, 介面可以定義類別行為, 內含常數和方法的宣告, 但是沒有實作的程式碼, 當類別實作介面時, 類別需要實作 所有 的介面方法 Java 介面可以宣告常數和方法, 其宣告的方法是一種抽象方法 (Abstract Method), 表示只有宣告沒有程式碼, 其語法如下所示 : public interface 介面名稱 { final 資料型態常數 = 值 ; 傳回值型態介面方法 ( 參數列 );
8-2-2 介面的建立與使用 - 宣告範例 例如 :IArea 介面宣告如下所示 : interface IArea { final double PI = 3.1415926; void area(); 介面擁有一個常數 PI 和方法 area(), 方法隱含宣告成 public 和 abstract( 抽象 ) 修飾子 ; 常數隱含宣告成 public final( 常數 ) 和 static 修飾子
8-2-2 介面的建立與使用 - 實作語法 Java 類別可以實作介面, 也就是建立介面方法的程式碼, 其宣告語法如下所示 : class 類別名稱 implements 介面名稱 1, 介面名稱 2 { // 實作的介面方法 類別使用 implements 關鍵字來實作介面, 如果實作介面不只一個, 請使用, 逗號分隔, 在類別宣告內需要實作所有介面的方法
8-2-2 介面的建立與使用 - 實作範例 例如 :Circle 類別實作 IArea 介面, 其類別宣告如下所示 : class Circle implements IArea { public void area() { System.out.println(" 圓面積 : " + PI*r*r);
8-2-2 介面的建立與使用 - 類別圖
8-2-3 在類別實作多個介面 - 介面宣告 Java 的單一個類別可以實作多個介面 例如 : IArea 和 IShow 兩個介面的宣告, 如下所示 : interface IArea { final double PI = 3.1415926; void area(); interface IShow { void show();
8-2-3 在類別實作多個介面 - 範例 Circle 類別可以同時實作 IArea 和 IShow 兩個介面, 其類別宣告如下所示 : class Circle implements IArea, IShow { public void area() { public void show() {
8-2-3 在類別實作多個介面 - 類別圖
8-3 介面的繼承 8-3-1 繼承介面 8-3-2 介面的多重繼承
8-3-1 繼承介面 - 語法 Java 可以使用介面繼承方式來擴充介面, 增加介面的抽象方法, 其宣告語法如下所示 : interface 介面名稱 extends 繼承的介面 { // 額外的常數和方法 宣告的介面繼承其他介面的所有常數和方法
8-3-1 繼承介面 - 範例 例如 : 繼承第 8-2-2 節的 IArea 介面, 其介面宣告如下所示 : interface IShape extends IArea { void perimeter(); 介面 IShape 繼承自 IArea 介面, 新增 perimeter() 介面方法
8-3-1 繼承介面 - 類別圖
8-3-2 介面的多重繼承 - 基礎 多重繼承表示父類別不只一個,Java 語言並不支援多重繼承 ;C++ 語言支援, 但是 Java 語言支援介面的多重繼承 多重繼承 (Multiple Inheritance) 是指一個類別能夠繼承多個父類別, 如右圖所示 :
8-3-2 介面的多重繼承 - 語法 在 Java 語言的介面支援多重繼承, 其宣告語法如下所示 : interface 介面名稱 extends 繼承的介面 1, 繼承的介面 2 { // 額外的常數和方法 介面宣告繼承多個介面, 各介面使用, 逗號分隔
8-3-2 介面的多重繼承 - 範例 例如 :IShape 介面繼承自 IArea 和 IShow 介面, 其介面宣告如下所示 : interface IShape extends IArea, IShow { void perimeter(); 介面 IShape 是繼承自 IArea 和 IShow 介面, 新增 perimeter() 方法
8-3-2 介面的多重繼承 - 類別圖
8-4 抽象類別 - 說明 Java 類別宣告如果使用 abstract 修飾子, 表示它是一個 抽象類別 (Abstract Class), 抽象類別並不能用來建立物件, 只能被繼承用來宣告子類別 在抽象類別的宣告也可以使用 abstract 宣告方法為抽象方法, 表示方法只有原型宣告, 實作程式碼是在子類別建立, 而且繼承的類別一定要實作抽象方法
8-4 抽象類別 - 宣告 抽象類別是建立子類別的原型, 抽象方法可以視為建立子類別的介面方法, 如果類別擁有抽象方法 ( 也可以擁有一般方法 ), 表示此類別是抽象類別 例如 :Account 抽象類別宣告, 如下所示 : abstract class Account { public String accountid; private double amount; public double interest; public abstract void calinterest(); public void setbalance(double a) { public double getbalance() {
8-4 抽象類別 - 繼承 接著宣告 SavingAccount 存款帳戶類別繼承 Account 帳戶類別, 其類別宣告如下所示 : class SavingAccount extends Account { public boolean havecard; public SavingAccount(String id, double amount, double interest, boolean havecard) { public void calinterest() { double amount = getbalance(); System.out.println(" 利息 : " + (amount*interest));
8-4 抽象類別 - 類別圖
8-5 抽象類別與介面 - 差異 抽象類別與介面的抽象類別與介面的主要差異, 如下所示 : 在抽象類別的方法可以宣告成抽象方法, 也可以是一般方法 ; 介面方法就只有宣告, 在介面一定不會有實作的程式碼 介面並不屬於類別的繼承架構 ; 抽象類別則屬於類別的繼承架構 抽象類別一定是繼承架構的父類別, 但是, 就算亳無關係的類別也一樣可以實作同一個介面 一個類別只能繼承一個抽象類別, 但是可以同時實作多個介面
8-5 抽象類別與介面 - 抽象類別宣告 Java 類別可以繼承抽象類別且實作介面 例如 : 圖形 Shape 的抽象類別, 其類別宣告如下所示 : abstract class Shape { public double x; public double y; public abstract void area();
8-5 抽象類別與介面 - 介面宣告 繼承 Shape 抽象類別的子類別可以同時實作介面, 例如 :IPerimeter 介面, 其介面宣告如下所示 : interface IPerimeter { void perimeter();
8-5 抽象類別與介面 - 繼承且實作 宣告 Rectangle 類別繼承自 Shape 抽象類別, 並且實作 IPerimeter 介面, 其類別宣告如下所示 : class Rectangle extends Shape implements IPerimeter { public void area() { System.out.println(" 長方形面積 :"+width*height); public void perimeter() { System.out.println(" 長方形周長 :"+2*(width+height));
8-5 抽象類別與介面 - 類別圖
8-5 抽象類別與介面 - 介面的物件變 數 因為 Java 介面也是一種參考資料型態, 換句話說, 我們一樣可以使用介面來宣告物件變數, 參考實作此介面的物件, 如下所示 : IPerimeter r3 = new Rectangle(15.0,15.0,4.0,8.0); 物件變數 r3 使用介面來宣告, 其參考的物件是 Rectangle 類別的物件 以口語來說 : Rectangle 物件就是一種實作 IPerimeter 介面的物件
8-6 常數類別 - 說明 Java 類別除了可以使用 public 和 abstract 類別修飾子外, 還提供 final 修飾子來宣告常數類別與常數方法 如果類別宣告成 final 表示類別不能被繼承 ; 如果方法宣告成 final 表示此方法不可以覆寫
8-6 常數類別 - 範例 常數類別是使用 final 修飾子進行宣告, 例如 : 繼承父類別 Person 的 Customer 類別, 其類別宣告如下所示 : final class Customer extends Person { Person 類別的方法宣告成 final, 其類別宣告如下所示 : class Person { public final String getname() { return name; public final String getaddress() { return address; public final void setname(string n) { name = n; public final void setaddress(string a) {address = a;