狠狠撸
Submit Search
Java SE 7 技術手冊第六章草稿 - 何謂繼承?
Feb 17, 2013
1 like
3,610 views
Justin Lin
Java SE 7 技術手冊
Read less
Read more
1 of 15
Download now
Downloaded 75 times
Recommended
《Python 3.5 技術手冊》第六章草稿
《Python 3.5 技術手冊》第六章草稿
Justin Lin
?
6.1 何謂繼承? 6.1.1 繼承共同行為 6.1.2 鴨子定型 6.1.3 重新定義方法 6.1.4 定義抽象方法 6.2 繼承語法細節 6.2.1 初識object與super() 6.2.2 Rich comparison方法 定義__eq__() 14 定義__gt__()、__ge__() 使用functools.total_ordering 6.2.3 多重繼承 6.2.4 建立ABC 6.2.5 探討super() 6.3 文件與套件資源 6.3.1 DocString 6.3.2 查詢官方文件 6.3.3 PyPI與pip 6.4 重點複習 34 課後練習
Java SE 8 技術手冊第 6 章 - 繼承與多型
Java SE 8 技術手冊第 6 章 - 繼承與多型
Justin Lin
?
瞭解繼承目的 瞭解繼承與多型的關係 知道如何重新定義方法 認識java.lang.Object 簡介垃圾收集機制
Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE
Java SE 7 技術手冊第二章草稿 - 從 JDK 到 IDE
Justin Lin
?
Java SE 7 技術手冊
Sun java
Sun java
softwaredesigner
?
SCJP ch17
SCJP ch17
r82093403
?
2, object oriented programming
2, object oriented programming
ted-xu
?
What is OOP? a basic intro
闯补惫补面试知识
闯补惫补面试知识
yiditushe
?
闯补惫补面试32题
闯补惫补面试32题
yiditushe
?
Java Script 引擎技术
Java Script 引擎技术
bigqiang zou
?
周爱民先生在SD2C大会讲的<JavaScript 引擎技术>
Java SE 7 技術手冊投影片第 04 章 - 認識物件
Java SE 7 技術手冊投影片第 04 章 - 認識物件
Justin Lin
?
Java SE 7 技術手冊
闯补惫补面试题集
闯补惫补面试题集
yiditushe
?
Java SE 7 技術手冊投影片第 12 章 - 通用API
Java SE 7 技術手冊投影片第 12 章 - 通用API
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器
Justin Lin
?
Java SE 7 技術手冊
第二章
第二章
贺 利华
?
主要讲述搁耻产测中的类继承,属性和变量相关的概念和知识
笔测迟丑辞苍面向对象开发基础篇
笔测迟丑辞苍面向对象开发基础篇
modou li
?
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行API
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行API
Justin Lin
?
Java SE 7 技術手冊
大公司的闯补惫补面试题集
大公司的闯补惫补面试题集
yiditushe
?
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Justin Lin
?
Java SE 7 技術手冊
[圣思园][Java SE]Reflection
[圣思园][Java SE]Reflection
ArBing Xie
?
闯补惫补面试笔试题大汇总
闯补惫补面试笔试题大汇总
yiditushe
?
闯补惫补物件导向
闯补惫补物件导向
艾鍗科技
?
艾鍗學院-闯补惫补物件导向課程
闯补惫补相关基础知识
闯补惫补相关基础知识
yiditushe
?
Java SE 7 技術手冊投影片第 09 章 - Collection與Map
Java SE 7 技術手冊投影片第 09 章 - Collection與Map
Justin Lin
?
Java SE 7 技術手冊
组合、备忘录、建造者模式、原型
组合、备忘录、建造者模式、原型
诸葛修车网-诸葛商城
?
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 本文档主要讲解其中的组合、备忘录、建造者模式、原型模式
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 08 章 - 例外處理
Java SE 7 技術手冊投影片第 08 章 - 例外處理
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊第七章草稿 - 何謂介面?
Java SE 7 技術手冊第七章草稿 - 何謂介面?
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊第五章草稿 - 何謂封裝?
Java SE 7 技術手冊第五章草稿 - 何謂封裝?
Justin Lin
?
Java SE 7 技術手冊
More Related Content
What's hot
(20)
Java Script 引擎技术
Java Script 引擎技术
bigqiang zou
?
周爱民先生在SD2C大会讲的<JavaScript 引擎技术>
Java SE 7 技術手冊投影片第 04 章 - 認識物件
Java SE 7 技術手冊投影片第 04 章 - 認識物件
Justin Lin
?
Java SE 7 技術手冊
闯补惫补面试题集
闯补惫补面试题集
yiditushe
?
Java SE 7 技術手冊投影片第 12 章 - 通用API
Java SE 7 技術手冊投影片第 12 章 - 通用API
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器
Justin Lin
?
Java SE 7 技術手冊
第二章
第二章
贺 利华
?
主要讲述搁耻产测中的类继承,属性和变量相关的概念和知识
笔测迟丑辞苍面向对象开发基础篇
笔测迟丑辞苍面向对象开发基础篇
modou li
?
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行API
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行API
Justin Lin
?
Java SE 7 技術手冊
大公司的闯补惫补面试题集
大公司的闯补惫补面试题集
yiditushe
?
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Justin Lin
?
Java SE 7 技術手冊
[圣思园][Java SE]Reflection
[圣思园][Java SE]Reflection
ArBing Xie
?
闯补惫补面试笔试题大汇总
闯补惫补面试笔试题大汇总
yiditushe
?
闯补惫补物件导向
闯补惫补物件导向
艾鍗科技
?
艾鍗學院-闯补惫补物件导向課程
闯补惫补相关基础知识
闯补惫补相关基础知识
yiditushe
?
Java SE 7 技術手冊投影片第 09 章 - Collection與Map
Java SE 7 技術手冊投影片第 09 章 - Collection與Map
Justin Lin
?
Java SE 7 技術手冊
组合、备忘录、建造者模式、原型
组合、备忘录、建造者模式、原型
诸葛修车网-诸葛商城
?
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 本文档主要讲解其中的组合、备忘录、建造者模式、原型模式
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 08 章 - 例外處理
Java SE 7 技術手冊投影片第 08 章 - 例外處理
Justin Lin
?
Java SE 7 技術手冊
Java Script 引擎技术
Java Script 引擎技术
bigqiang zou
?
Java SE 7 技術手冊投影片第 04 章 - 認識物件
Java SE 7 技術手冊投影片第 04 章 - 認識物件
Justin Lin
?
闯补惫补面试题集
闯补惫补面试题集
yiditushe
?
Java SE 7 技術手冊投影片第 12 章 - 通用API
Java SE 7 技術手冊投影片第 12 章 - 通用API
Justin Lin
?
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器
Java SE 7 技術手冊投影片第 15 章 - 反射器與類別載入器
Justin Lin
?
第二章
第二章
贺 利华
?
笔测迟丑辞苍面向对象开发基础篇
笔测迟丑辞苍面向对象开发基础篇
modou li
?
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Justin Lin
?
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行API
Java SE 7 技術手冊投影片第 11 章 - 執行緒與並行API
Justin Lin
?
大公司的闯补惫补面试题集
大公司的闯补惫补面试题集
yiditushe
?
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Java SE 7 技術手冊投影片第 06 章 - 繼承與多型
Justin Lin
?
[圣思园][Java SE]Reflection
[圣思园][Java SE]Reflection
ArBing Xie
?
闯补惫补面试笔试题大汇总
闯补惫补面试笔试题大汇总
yiditushe
?
闯补惫补物件导向
闯补惫补物件导向
艾鍗科技
?
闯补惫补相关基础知识
闯补惫补相关基础知识
yiditushe
?
Java SE 7 技術手冊投影片第 09 章 - Collection與Map
Java SE 7 技術手冊投影片第 09 章 - Collection與Map
Justin Lin
?
组合、备忘录、建造者模式、原型
组合、备忘录、建造者模式、原型
诸葛修车网-诸葛商城
?
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出
Java SE 7 技術手冊投影片第 10 章 - 輸入輸出
Justin Lin
?
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫
Java SE 7 技術手冊投影片第 14 章 - 整合資料庫
Justin Lin
?
Java SE 7 技術手冊投影片第 08 章 - 例外處理
Java SE 7 技術手冊投影片第 08 章 - 例外處理
Justin Lin
?
Viewers also liked
(11)
Java SE 7 技術手冊第七章草稿 - 何謂介面?
Java SE 7 技術手冊第七章草稿 - 何謂介面?
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊第五章草稿 - 何謂封裝?
Java SE 7 技術手冊第五章草稿 - 何謂封裝?
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 07 章 - 介面與多型
Java SE 7 技術手冊投影片第 07 章 - 介面與多型
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 05 章 - 物件封裝
Java SE 7 技術手冊投影片第 05 章 - 物件封裝
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計
Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 02 章 - 從JDK到IDE
Java SE 7 技術手冊投影片第 02 章 - 從JDK到IDE
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊 - 課後練習解答
Java SE 7 技術手冊 - 課後練習解答
Justin Lin
?
Java SE 7 技術手冊
Java SE 8 技術手冊第 1 章 - Java平台概論
Java SE 8 技術手冊第 1 章 - Java平台概論
Justin Lin
?
簡介Java版本遷移 認識Java SE、Java EE、Java ME 認識JDK規範與實作 瞭解JVM、JRE與JDK 下載、安裝JDK
Java SE 7 技術手冊投影片第 01 章 - Java平台概論
Java SE 7 技術手冊投影片第 01 章 - Java平台概論
Justin Lin
?
Java SE 7 技術手冊
Java SE 7 技術手冊投影片第 03 章 - 基礎語法
Java SE 7 技術手冊投影片第 03 章 - 基礎語法
Justin Lin
?
Java SE 7 技術手冊
Java SE 8 技術手冊第 2 章 - 從JDK到IDE
Java SE 8 技術手冊第 2 章 - 從JDK到IDE
Justin Lin
?
瞭解與設定PATH 瞭解與指定CLASSPATH 瞭解與指定SOURCEPATH 使用package與import管理類別 初步認識JDK與IDE的對應
Java SE 7 技術手冊第七章草稿 - 何謂介面?
Java SE 7 技術手冊第七章草稿 - 何謂介面?
Justin Lin
?
Java SE 7 技術手冊第五章草稿 - 何謂封裝?
Java SE 7 技術手冊第五章草稿 - 何謂封裝?
Justin Lin
?
Java SE 7 技術手冊投影片第 07 章 - 介面與多型
Java SE 7 技術手冊投影片第 07 章 - 介面與多型
Justin Lin
?
Java SE 7 技術手冊投影片第 05 章 - 物件封裝
Java SE 7 技術手冊投影片第 05 章 - 物件封裝
Justin Lin
?
Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計
Java SE 7 技術手冊投影片第 13 章 - 視窗程式設計
Justin Lin
?
Java SE 7 技術手冊投影片第 02 章 - 從JDK到IDE
Java SE 7 技術手冊投影片第 02 章 - 從JDK到IDE
Justin Lin
?
Java SE 7 技術手冊 - 課後練習解答
Java SE 7 技術手冊 - 課後練習解答
Justin Lin
?
Java SE 8 技術手冊第 1 章 - Java平台概論
Java SE 8 技術手冊第 1 章 - Java平台概論
Justin Lin
?
Java SE 7 技術手冊投影片第 01 章 - Java平台概論
Java SE 7 技術手冊投影片第 01 章 - Java平台概論
Justin Lin
?
Java SE 7 技術手冊投影片第 03 章 - 基礎語法
Java SE 7 技術手冊投影片第 03 章 - 基礎語法
Justin Lin
?
Java SE 8 技術手冊第 2 章 - 從JDK到IDE
Java SE 8 技術手冊第 2 章 - 從JDK到IDE
Justin Lin
?
More from Justin Lin
(20)
Ch14 簡介 Spring Boot
Ch14 簡介 Spring Boot
Justin Lin
?
認識 Spring Boot 認識 Spring Tool Suite 遷移微網誌至 Spring Boot
Ch13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/Security
Justin Lin
?
區別程式庫與框架 逐步善用 Spring MVC 簡介 Thymeleaf 模版 使用 Spring Security
Ch12 Spring 起步走
Ch12 Spring 起步走
Justin Lin
?
使用 Gradle 結合 Gradle 與 IDE 認識相依注入 使用 Spring 核心
Ch11 簡介 JavaMail
Ch11 簡介 JavaMail
Justin Lin
?
寄送純文字郵件 寄送 HTML 郵件 寄送附檔郵件
Ch10 Web 容器安全管理
Ch10 Web 容器安全管理
Justin Lin
?
了解 Java EE 安全概念與名詞 使用容器基本驗證與表單驗 使用 HTTPS 保密資料傳輸
Ch09 整合資料庫
Ch09 整合資料庫
Justin Lin
?
了解 JDBC 架構 使用基本的 JDBC 透過 JNDI 取得DataSource 在 Web 應用程式整合資料庫
Ch08 自訂標籤
Ch08 自訂標籤
Justin Lin
?
使用 Tag File 自訂標籤 使用 Simple Tag 自訂標籤 使用 Tag 自訂標籤
Ch07 使用 JSTL
Ch07 使用 JSTL
Justin Lin
?
了解何謂 JSTL 使用 JSTL 核心標籤庫 使用 JSTL 格式標籤庫 使用 JSTL XML 標籤庫 使用 JSTL 函式標籤庫
Ch06 使用 JSP
Ch06 使用 JSP
Justin Lin
?
了解 JSP 生命週期 使用 JSP 語法元素 使用 JSP 標準標籤 使用運算式語言(EL) 自訂 EL 函式
Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器
Justin Lin
?
了解 Servlet 生命週期 使用 ServletConfig 與ServletContext 使用 PushBuilder 各種傾聽器的使用 繼承 HttpFilter 實作過濾器
Ch04 會話管理
Ch04 會話管理
Justin Lin
?
了解會話管理基本原理 使用 Cookie 類別 使用 HttpSession 會話管理 了解容器會話管理原理
Ch03 請求與回應
Ch03 請求與回應
Justin Lin
?
取得請求參數與標頭 處理中文字元請求與回應 設定與取得請求範圍屬性 使用轉發、包含、重新導向
Ch02 撰寫與設定 Servlet
Ch02 撰寫與設定 Servlet
Justin Lin
?
開發環境準備與使用 了解 Web 應用程式架構 Servlet 撰寫與部署設定 了解 URI 模式對應 使用 web-fragement.xml
CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式
Justin Lin
?
認識 HTTP 基本特性 了解何為 URI 編碼 認識 Web 容器角色 了解 Servlet 與 JSP 的關係 認識 MVC/Model 2
14. 進階主題
14. 進階主題
Justin Lin
?
運用描述器 實作裝飾器 定義 meta 類別 使用相對匯入 泛型進階
13.并行、平行与非同步
13.并行、平行与非同步
Justin Lin
?
認識並行、平行與非同步 使用 threading 模組 使用 multiprocessing 模組 使用 concurrent.futures模組 運用 async、await 與 asyncio
12. 除錯、測試與效能
12. 除錯、測試與效能
Justin Lin
?
使用 pdb 模組除錯 對程式進行單元測試 使用 timeit 評測程式片段 使用 cProfile(profile)察看評測數據
11. 常用內建模組
11. 常用內建模組
Justin Lin
?
處理日期與時間 認識日誌的使用 運用規則表示式 管理檔案與目錄 URL 處理
10. 資料永續與交換
10. 資料永續與交換
Justin Lin
?
使用 pickle 與 shelve 認識 DB-API 2.0 使用 sqlite3 模組 處理 CSV、JSON、XML
9. 資料結構
9. 資料結構
Justin Lin
?
認識 hashable、iterable、orderable 對物件進行排序 認識群集架構 運用 collections 模組 運用 collections.abc 模組
Ch14 簡介 Spring Boot
Ch14 簡介 Spring Boot
Justin Lin
?
Ch13 整合 Spring MVC/Security
Ch13 整合 Spring MVC/Security
Justin Lin
?
Ch12 Spring 起步走
Ch12 Spring 起步走
Justin Lin
?
Ch11 簡介 JavaMail
Ch11 簡介 JavaMail
Justin Lin
?
Ch10 Web 容器安全管理
Ch10 Web 容器安全管理
Justin Lin
?
Ch09 整合資料庫
Ch09 整合資料庫
Justin Lin
?
Ch08 自訂標籤
Ch08 自訂標籤
Justin Lin
?
Ch07 使用 JSTL
Ch07 使用 JSTL
Justin Lin
?
Ch06 使用 JSP
Ch06 使用 JSP
Justin Lin
?
Ch05 Servlet 進階 API、過濾器與傾聽器
Ch05 Servlet 進階 API、過濾器與傾聽器
Justin Lin
?
Ch04 會話管理
Ch04 會話管理
Justin Lin
?
Ch03 請求與回應
Ch03 請求與回應
Justin Lin
?
Ch02 撰寫與設定 Servlet
Ch02 撰寫與設定 Servlet
Justin Lin
?
CH1. 簡介 Web 應用程式
CH1. 簡介 Web 應用程式
Justin Lin
?
14. 進階主題
14. 進階主題
Justin Lin
?
13.并行、平行与非同步
13.并行、平行与非同步
Justin Lin
?
12. 除錯、測試與效能
12. 除錯、測試與效能
Justin Lin
?
11. 常用內建模組
11. 常用內建模組
Justin Lin
?
10. 資料永續與交換
10. 資料永續與交換
Justin Lin
?
9. 資料結構
9. 資料結構
Justin Lin
?
Java SE 7 技術手冊第六章草稿 - 何謂繼承?
1.
Java SE 7
稿 草冊手術技 何謂繼承 繼承? 6.1 何謂繼承? 物件導向中,子類別繼承(Inherit)父類別,避免重複的行為定義,不過並非為 了避免重複定義行為就使用繼承,濫用繼承而導致程式維護上的問題時有所聞,如何 正確判斷使用繼承的時機,以及繼承之後如何活用多型,才是學習繼承時的重點。 繼承共同行為 6.1.1 繼承共同行為 繼承基本上就是避免多個類別間重複定義共同行為。以實際的例子來說明比較清 楚,假設你在正開發一款 RPG(Role-playing game)遊戲,一開始設定的角色有劍 士與魔法師。首先你定義了劍士類別: public class SwordsMan { private String name; // 稱名色角 private int level; // 級等色角 private int blood; // 量血色角 public void fight() { System.out.println(" 擊攻劍揮 "); } public int getBlood() { return blood; } public void setBlood(int blood) { this.blood = blood; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public String getName() { return name; } public void setName(String name) {
2.
Java SE 7
稿 草冊手術技 this.name = name; } } 接著你為魔法師定義類別: public class Magician { private String name; // 稱名色角 稱名色角 稱名色角 稱名色角 private int level; // 級等色角 級等色角 級等色角 級等色角 private int blood; // 量血色角 量血色角 量血色角 量血色角 public void fight() { System.out.println(" 擊攻法魔 "); } public void cure() { System.out.println(" 療治法魔 "); } public int getBlood() { return blood; } public void setBlood(int blood) { this.blood = blood; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
3.
Java SE 7
稿 草冊手術技 你注意到什麼呢?因為只要是遊戲中的角色,都會具有角色名稱、等級與血量, 類別中也都為名稱、等級與血量定義了取值方法與設值方法,Magician 中粗體字部 重複在程式設計上, 重複在程式設計上 就是不好的訊號 不好的訊號。 份與 SwordsMan 中相對應的程式碼重複了。重複在程式設計上,就是不好的訊號 舉個例子來說,如果你要將 name、level、blood 改名為其它名稱,那就要修改 SwordsMan 與 Magician 兩個類別,如果有更多類別具有重複的程式碼,那就要修 改更多類別,造成維護上的不便。 如果要改進,可以把相同的程式碼提昇(Pull up)為父類別: Lab Game1 Role.java package cc.openhome; public class Role { private String name; private int level; private int blood; public int getBlood() { return blood; } public void setBlood(int blood) { this.blood = blood; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } public String getName() { return name; } public void setName(String name) { this.name = name; }
4.
Java SE 7
稿 草冊手術技 } 這個類別在定義上沒什麼特別的新語法,只不過是將 SwordsMan 與 Magician Lab 中重複的程式碼複製過來。接著 SwordsMan 可以如下繼承 Role: Game1 SwordsMan.java package cc.openhome; public class SwordsMan extends Role { public void fight() { System.out.println(" 擊攻劍揮 "); } } 在這邊看到了新的關鍵字 extends,這表示 SwordsMan 會擴充 Role 的行為, 也就是繼承 Role 的行為,再擴充 Role 原本沒有的 fight()行為。程式面上來說, Role 中有定義的程式碼,SwordsMan 中都繼承而擁有了,並再定義了 fight()方 Lab 法的程式碼。類似地,Magician 也可以如下定義繼承 Role 類別: Game1 Magician.java package cc.openhome; public class Magician extends Role { public void fight() { System.out.println(" 擊攻法魔 "); } public void cure() { System.out.println(" 療治法魔 "); } } SwordsMan 繼承 Role 的行為 再擴充了 Role 原本沒有的 fight()與 cure() , 行為。
5.
Java SE 7
稿 草冊手術技 提示 在這個類別圖中,第一格中 Role 表示類別名稱,第二格中 name、 level 、 blood 表 示 資 料 成 員 , : 號 之 後 為 各 成 員 型 態 , - 號 表 示 private,第三格表示方法名稱,+號表示 public,:號之後表示傳回 型態,繼承則以空心箭頭表示。 Lab 如何看出確實有繼承了呢?以下簡單的程式可以看出: Game1 RPG.java package cc.openhome; public class RPG { public static void main(String[] args) { SwordsMan swordsMan = new SwordsMan(); swordsMan.setName("Justin"); swordsMan.setLevel(1); swordsMan.setBlood(200); System.out.printf(" :士劍 (%s, %d, %d)%n", swordsMan.getName(), swordsMan.getLevel(), swordsMan.getBlood()); Magician magician = new Magician(); magician.setName("Monica");
6.
Java SE 7
稿 草冊手術技 magician.setLevel(1); magician.setBlood(100); System.out.printf(" :師法魔 (%s, %d, %d)%n", magician.getName(), magician.getLevel(), magician.getBlood()); } } 雖然 SwordsMan 與 Magician 並沒有定義 getName()、getLevel()與 getBlood()等方法,但從 Role 繼承了這些方法,所以就如範例中可以直接使用, 執行的結果如下: :士劍 (Justin, 1, 200) :師法魔 (Monica, 1, 100) 繼承的好處之一,就是若你要將 name、level、blood 改名為其它名稱,那就 只要修改 Role.java 就可以了,只要是繼承 Role 的子類別都無需修改。 注意 有 的 書 籍 或 文 件 會 說 , private 成 員 無 法 繼 承 , 那 是 錯 的 ! 如 果 private 成員無法繼承,那為什麼上面的範例 name、level、blood 記錄的值會顯示出來呢?private 成員會被繼承,只不過子類別無法直 接存取,必須透過父類別提供的方法來存取(如果父類別願意提供存取 方法的話) 。 6.1.2 多型與 is-a 子類別只能繼承一個父類別,繼承除了可避免類別間重複的行為定 在 Java 中,子類別只能繼承一個父類別 子類別只能繼承一個父類別 義外,還有個重要的關係,那就是子類別與父類別間會有 is-a 的關係,中文稱為「是 「 一種」 一種」的關係,這是什麼意思?以先前範例來說,SwordsMan 繼承了 Role,所以 SwordsMan 是一種 Role(SwordsMan is a Role) ( ),Magician 繼承了 Role,所 以 Magician 是一種 Role(Magician is a Role) ( )。 為何要知道繼承時,父類別與子類別間會有「是一種」的關係?因為要開始理解 多型(Polymorphism) ,必須先知道你操作的物件是「哪一種」東西! 來看實際的例子,以下的程式碼片段,相信你現在沒有問題地看懂,而且知道可 以通過編譯: SwordsMan swordsMan = new SwordsMan(); Magician magician = new Magician(); 那你知道以下的程式片段也可以通過編譯嗎? Role role1 = new SwordsMan(); Role role2 = new Magician(); 那你知道以下的程式片段為何無法通過編譯呢? SwordsMan swordsMan = new Role(); Magician magician = new Role();
7.
Java SE 7
稿 草冊手術技 編譯器就是語法檢查器,要知道以上程式片段為何可以通過編譯,為何無法通過 編譯,就是將自己當作編譯器,檢查語法的邏輯是否正確,方式是從 號右邊往左讀: 方式是從=號右邊往左讀 方式是從 右邊是不是一種左邊呢(右邊型態是不是左邊型態的子類別)? 圖 5.1 運用 is a 關係判斷語法正確性 從右往左讀,SwordsMan 是不是一 種 Role 呢?是的 ! 所以編譯通過。 Magician 是不是一種 Role 呢?是的!所以編譯通過。同樣的判斷方式,可以知道 為何以下編譯失敗: SwordsMan swordsMan = new Role(); // Role 種一是不是 SwordsMan ? Magician magician = new Role(); // Role 種一是不是 Magician ? 編譯器認為第一行,Role 不一定是一種 SwrodsMan,所以編譯失敗,對於第 二行,編譯器認為 Role 不一定是一種 Magician,所以編譯失敗。繼續把自己當成 編譯器,再來看看以下的程式片段是否可以通過編譯: Role role1 = new SwordsMan(); SwordsMan swordsMan = role1; 這個程式片段最後會編譯失敗,先從第一行看,SwordsMan 是一種 Role,所 以這行可以通過編譯。編譯器檢查這類語法,一次只看一行,就第二行而言,編譯器 看到 role1 為 Role 宣告的名稱,於是檢查 Role 是不是一種 SwordsMan,答案是 不一定,所以編譯失敗在第二行! 編譯器會檢查父子類別間的「是一種」關係,如果你不想要編譯器囉嗦,可以叫 它住嘴: Role role1 = new SwordsMan(); SwordsMan swordsMan = (SwordsMan) role1; 對於第二行,原本編譯器想囉嗦地告訴你,Role 不一定是一種 SwordsMan, 但你加上了(SwordsMan)讓它住嘴了,因為這表示,你就是要讓 Role 扮演 CAST) ( ) SwrodsMan,既然你都明確要求編譯器別囉嗦了,編譯器就讓這段程式碼通過編譯 不過後果得自行負責! 了,不過後果得自行負責 不過後果得自行負責
8.
Java SE 7
稿 草冊手術技 以上面這個程式片段來說,role1 確實參考至 SwordsMan 實例,所以在第二行 扮演 讓 SwordsMan 實例扮演 SwordsMan 並沒有什麼問題,所以執行時期並不會出錯。 圖 5.2 判斷是否可扮演(CAST)成功 判斷是否可扮演( ) 但是以下的程式片段,編譯可以成功,但執行時期會出錯: Role role2 = new Magician(); SwordsMan swordsMan = (SwordsMan) role2; 對於第一行,Magician 是一種 Role,可以通過編譯,對於第二行,role2 為 Role 型態,編譯器原本認定 Role 不一定是一種 SwordsMan 而想要囉嗦,但是你 明確告訴編譯器,就是要讓 Role 扮演為 SwordsMan,所以編譯器就讓你通過編譯 了,不過後果自負,實際上,role2 參考的是 Magician,你要讓魔法師假扮為劍 士?這在執行上會是個錯誤,JVM 會拋出 java.lang.ClassCastException。 扮演( )失敗,執行時拋出 圖 5.3 扮演(CAST)失敗,執行時拋出 ClassCastException 使用有一種(is-a)原則,你就可以判斷,何時編譯成功,何時編譯失敗,以及
9.
Java SE 7
稿 草冊手術技 將扮演(CAST)看作是叫編譯器住嘴語法,並留意參考的物件實際型態,你就可以 判斷何時扮演成功,何時會拋出 ClassCastException。例如以下編譯成功,執行 也沒問題: SwordsMan swordsMan = new SwordsMan(); Role role = swordsMan; // SwordsMan 種一是 Role 以下程式片段會編譯失敗: SwordsMan swordsMan = new SwordsMan(); Role role = swordsMan; 種一是 // SwordsMan Role 譯編 過通行 這, SwordsMan swordsMan = role; // Role 種一是定一不 敗失譯 編, SwordsMan 以下程式片段編譯成功,執行時也沒問題: SwordsMan swordsMan = new SwordsMan(); Role role = swordsMan; // SwordsMan 種一是 Role 譯 編過 通行這 , // 讓要器 譯編訴告你 Role 演扮 SwordsMan 譯編 過通行這 下以, SwordsMan swordsMan = (SwordsMan) role; 考參 // role SwordsMan 功成行 執,例實 以下程式片段編譯成功,但執行時拋出 ClassCastException: SwordsMan swordsMan = new SwordsMan(); Role role = swordsMan; // SwordsMan 種一是 Role 譯編 過通行 這, // 讓要器 譯編訴告你 Role 演扮 Magician 譯 編過通行 這 下以, 考參 Magician magician = (Magician) role; // role SwordsMan 敗失 行執,例 實 經過以上這一連串的語法測試,好像只是在玩弄語法?不!你懂不懂以上這些東 西,牽涉到寫出來的東西有沒有彈性、好不好維護的問題! 有這麼嚴重嗎?來出個題目給你吧!請設計 static 方法,顯示所有角色的血 量!OK!上一章剛學過如何定義方法,有的人會撰寫以下的方法定義: public static void showBlood(SwordsMan swordsMan) { System.out.printf("%s 量血 %d%n", swordsMan.getName(), swordsMan.getBlood()); } public static void showBlood(Magician magician) { System.out.printf("%s 量血 %d%n", magician.getName(), magician.getBlood()); } 分別為 SwordsMan 與 Magician 設計 showBlood()同名方法,這是重載方法 的運用,如此就可以如下呼叫: showBlood(swordsMan); // swordsMan 是 態型 SwordsMan showBlood(magician); // magician 是Magician 態型 現在的問題是,目前你的遊戲中是只有 SwordsMan 與 Magician 兩個角色,如 果有一百個角色呢?重載出一百個方法?這種方式顯然不可能!如果所有角色都是 繼承自 Role,而且你知道這些角色都是一種 Role,你就可以如下設計方法並呼叫:
10.
Java SE 7
稿 草冊手術技 Game2 RPG.java package cc.openhome; 宣告為 Role 型態 public class RPG { public static void showBlood(Role role) { System.out.printf("%s 量血 %d%n", role.getName(), role.getBlood()); } public static void main(String[] args) { SwordsMan swordsMan = new SwordsMan(); swordsMan.setName("Justin"); swordsMan.setLevel(1); swordsMan.setBlood(200); Magician magician = new Magician(); magician.setName("Monica"); magician.setLevel(1); magician.setBlood(100); showBlood(swordsMan); SwordsMan 是一種 Role showBlood(magician); Magician 是一種 Role } } 在這邊僅定義了一個 showBlood()方法,參數宣告為 Role 型態 ,第一次呼 叫 showBlood()時傳入了 SwordsMan 實例,這是合法的語法,因為 SwordsMan 是一種 Role ,第一次呼叫 showBlood()時傳入了 Magician 實例也是可行,因 為 Magician 是一種 Role 。執行的結果如下: Justin 量血 200 Monica 量血 100 這樣的寫法好處為何?就算有 100 種角色,只要它們都是繼承 Role,都可以使 用這個方法顯示角色的血量,而不需要像先前重載的方式,為不同角色寫 100 個方 法,多型的寫法顯然具有更高的可維護性。 使用單一介面操作多種型態的物件!若用以 使用單一介面操作多種型態的物件 什麼叫多型?以抽象講法解釋,就是使用單一介面操作多種型態的物件 上的範例來理解,在 showBlood()方法中,既可以透過 Role 型態操作 SwordsMan 物件,也可以透過 Role 型態操作 Magician 物件。 注意 稍後會學到 Java 中 interface 的使用,在多型定義中,使用單一介面 操作多種型態的物件,這邊的介面並不是專指 Java 中的 interface,
11.
Java SE 7
稿 草冊手術技 而是指物件上可操作的方法。 重新定義行為 6.1.3 重新定義行為 現在有個需求,請設計 static 方法,可以播放角色攻擊動畫,你也許會這麼想, 學剛剛多型的寫法,設計個 drawFight()方法如何? 圖 5.4 Role 沒有定義 fight()方法 方法 對 drawFight()方法而言,只知道傳進來的會是一種 Role 物件,所以編譯器 也只能檢查你呼叫的方法,Role 是不是有定義,顯然地,Role 目前並沒有定義 fight()方法,因此編譯錯誤了。 然而你仔細觀察一下 SwordsMan 與 Magician 的 fight()方法,他們的方法 方法 簽署( 簽署(method signature)都是: ) public void fight() 也就是說,操作介面是相同的,只是方法實作內容不同,你可以將 fight()方 Lab 法提昇至 Role 類別中定義: Game3 Role.java package cc.openhome; public class Role { ... 略 public void fight() { // 義定新重要別類子 義定新重要別類子 義定新重要別類子 義定新重要別類子 為行際實的 為行際實的 為行際實的 fight() 為行際實的 } } 在 Role 類別中定義了 fight()方法,由於實際上角色如何攻擊,只有子類別 才知道,所以這邊的 fight()方法內容是空的,沒有任何程式碼實作。SwordsMan 繼承 Role 之後,再對 fight()的行為進行定義: Game3 SwordsMan.java package cc.openhome; public class SwordsMan extends Role {
12.
Java SE 7
稿 草冊手術技 public void fight() { System.out.println(" 擊攻劍揮 擊攻劍揮 擊攻劍揮 擊攻劍揮"); } } 在繼承父類別之後,定義與父類別中相同的方法簽署,但實作內容不同,這稱為 重新定義( 重新定義(Override) ),因為對父類別中已定義的方法實作不滿意,所以你在子類別 中重新定義實作。Magician 繼承 Role 之後,也重新定義了 fight()的行為: Game3 Magician.java package cc.openhome; public class Magician extends Role { public void fight() { System.out.println(" 擊攻法魔 擊攻法魔 擊攻法魔 擊攻法魔"); } ... 略 } 由於 Role 現在定義了 fight()方法(雖然方法區塊中沒有程式碼實作) ,所以 編譯器不會找不到 Role 的 fight()了,因此你可以如下撰寫: Game3 RPG.java package cc.openhome; 宣告為 Role 型態 public class RPG { public static void drawFight(Role role) { System.out.print(role.getName()); role.fight(); } public static void main(String[] args) { SwordsMan swordsMan = new SwordsMan(); swordsMan.setName("Justin"); swordsMan.setLevel(1); swordsMan.setBlood(200); Magician magician = new Magician(); magician.setName("Monica"); magician.setLevel(1); magician.setBlood(100);
13.
Java SE 7
稿 草冊手術技 drawFight(swordsMan); 實際操作的是 SwordsMan 實例 drawFight(magician); 實際操作的是 Magician 實例 } } 在 fight()方法宣告了 Role 型態的參數 ,那方法中呼叫的,到底是 Role 中 定義的 fight(),還是個別子類別中定義的 fight()呢?如果傳入 fight()的是 SwordsMan,role 參數參考的就是 SwordsMan 實例,操作的就是 SwordsMan 上 的方法定義: 圖 5.5 role 牌子掛在 SwordsMan 實例 這就好比 role 牌子掛在 SwordsMan 實例身上,你要求有 role 牌子的物件攻 擊,發動攻擊的物件就是 SwordsMan 實例。同樣地,如果傳入 fight()的是 Magician,role 參數參考的就是 Magician 實例,操作的就是 Magician 上的方 法定義: 圖 5.6 role 牌子掛在 Magician 實例 所以範例最後的執行結果是: Justin 擊攻劍揮 Monica 擊攻法魔 在重新定義父類別中某個方法時,子類別必須撰寫與父類別方法中相同的簽署, 然而如果疏忽打錯字了: public class SwordsMan extends Role {
14.
Java SE 7
稿 草冊手術技 public void Fight() { System.out.println(" 擊攻劍揮 "); } } 以這邊的例子來說,父類別中定義的是 fight(),但子類別中定義了 Fight(), 這就不是重新定義 fight()了,而是子類別新定義了一個 Fight()方法,這是合法 的方法定義,編譯器並不會發出任何錯誤訊息,你只會在運行範例時,發現為什麼 SwordsMan 完全沒有攻擊。 在 JDK5 之 後 支 援 標 註 ( Annotation ) 其 中 一 個 內 建 的 標 準 標 註 就 是 , @Override,如果你在子類別中某個方法前標註@Override,表示要求編譯器檢 查,該方法是不是真的重新定義了父類別中某個方法,如果不是的話,就會引發編譯 錯誤。例如: 圖 5.7 編譯器檢查是否真的重新定義父類別某方法 編譯器檢查是否真的重新定義父類別某方法 如果你要重新定義某方法,加上@Override,就不用擔心打錯字的問題了。關 於標註詳細語法,會在之後章節說明。 抽象方法、 6.1.4 抽象方法、抽象類別 上一個範例中 Role 類別的定義中,fight()方法區塊中實際上沒有撰寫任何程 式碼,雖然滿足了多型需求,但會引發的問題是,你沒有任何方式強迫或提示子類別 一定要實作 fight()方法,只能口頭或在文件上告知,不過如果有人沒有傳達到、 沒有看文件或文件看漏了呢? 如果某方法區塊中真的沒有任何程式碼實作,可以使用 abstract 標示該方法 Lab 為抽象方法(Abstract method) 抽象方法( 抽象方法 ,該方法不用撰寫{}區塊,直接;結束即可。例如: ) Game4 Role.java package cc.openhome; public abstract class Role { ... 略
15.
Java SE 7
稿 草冊手術技 public abstract void fight(); } 類別中若有方法沒有實作,並且標示為 abstract,表示這個類別定義不完整, 定義不完整的類別就不能用來生成實例 就不能用來生成實例,這就好比設計圖不完整,不能用來生產成品 定義不完整的類別就不能用來生成實例 中規定內含抽象方法的類別 的類別, 一樣。Java 中規定內含抽象方法的類別,一定要在 class 前標示 abstract,如上 抽象類別( 例所示,這表示這是一個定義不完整的抽象類別(Abstract class) 抽象類別 )。如果嘗試用抽 象類別建構實例,就會引發編譯錯誤: 圖 5.8 不能實例化抽象類別 子類別如果繼承抽象類別,對於抽象方法有兩種作法,一種作法是繼續標示該方 法為 abstract (該子類別因此也是個抽象類別 必須在 class 前標示 abstract) , , 另一個作法就是實作抽象方法。如果兩個作法都沒實施,就會引發編譯錯誤: 圖 5.9 沒有實作抽象方法 6.2 繼承語法細節 上一節介紹了繼承的基礎觀念與語法,然而結合 Java 的特性,繼承還有許多細 節必須明瞭 像是哪些成員可以限定在子類別中使用 哪些方法簽署算重新定義 Java , 、 、 中所有物件都是一種 java.lang.Object 等細節,這將於本節中詳細說明。 6.2.1protected 成員 就上一節的 RPG 遊戲來說,如果建立了一個角色,想顯示角色的細節,必須如 下撰寫: SwordsMan swordsMan = new SwordsMan(); ... 略 System.out.printf(" 士劍 士劍 士劍 士劍 (%s, %d, %d)%n", swordsMan.getName(), swordsMan.getLevel(), swordsMan.getBlood()); Magician magician = new Magician(); ... 略 System.out.printf(" 師法魔 師法魔 師法魔 師法魔 (%s, %d, %d)%n", magician.getName(),