就其本身來說
對象的概念可為我們帶來極大的便利
它在概念上允許我們將各式各樣數據和功能封裝到一起
這樣便可恰當表達
問題空間
的概念
不用刻意遵照基礎機器的表達方式
在程序設計語言中
這些概念則反映為具體的數據類型(使用class關鍵字)
我們費盡心思做出一種數據類型後
假如不得不又新建一種類型
令其實現大致相同的功能
那會是一件非常令人灰心的事情
但若能利用現成的數據類型
對其進行
克隆
再根據情況進行添加和修改
情況就顯得理想多了
繼承
正是針對這個目標而設計的
但繼承並不完全等價於克隆
在繼承過程中
若原始類(正式名稱叫作基礎類
超類或父類)發生了變化
修改過的
克隆
類(正式名稱叫作繼承類或者子類)也會反映出這種變化
在Java語言中
繼承是通過extends關鍵字實現的
使用繼承時
相當於創建了一個新類
這個新類不僅包含了現有類型的所有成員(盡管private成員被隱藏起來
且不能訪問)
但更重要的是
它復制了基礎類的接口
也就是說
可向基礎類的對象發送的所有消息亦可原樣發給衍生類的對象
根據可以發送的消息
我們能知道類的類型
這意味著衍生類具有與基礎類相同的類型!為真正理解面向對象程序設計的含義
首先必須認識到這種類型的等價關系
由於基礎類和衍生類具有相同的接口
所以那個接口必須進行特殊的設計
也就是說
對象接收到一條特定的消息後
必須有一個
方法
能夠執行
若只是簡單地繼承一個類
並不做其他任何事情
來自基礎類接口的方法就會直接照搬到衍生類
這意味著衍生類的對象不僅有相同的類型
也有同樣的行為
這一後果通常是我們不願見到的
有兩種做法可將新得的衍生類與原來的基礎類區分開
第一種做法十分簡單
為衍生類添加新函數(功能)
這些新函數並非基礎類接口的一部分
進行這種處理時
一般都是意識到基礎類不能滿足我們的要求
所以需要添加更多的函數
這是一種最簡單
最基本的繼承用法
大多數時候都可完美地解決我們的問題
然而
事先還是要仔細調查自己的基礎類是否真的需要這些額外的函數
改善基礎類 盡管extends關鍵字暗示著我們要為接口
擴展
新功能
但實情並非肯定如此
為區分我們的新類
第二個辦法是改變基礎類一個現有函數的行為
我們將其稱作
改善
那個函數
為改善一個函數
只需為衍生類的函數建立一個新定義即可
我們的目標是
盡管使用的函數接口未變
但它的新版本具有不同的表現
等價與類似關系 針對繼承可能會產生這樣的一個爭論
繼承只能改善原基礎類的函數嗎?若答案是肯定的
則衍生類型就是與基礎類完全相同的類型
因為都擁有完全相同的接口
這樣造成的結果就是
我們完全能夠將衍生類的一個對象換成基礎類的一個對象!可將其想象成一種
純替換
在某種意義上
這是進行繼承的一種理想方式
此時
我們通常認為基礎類和衍生類之間存在一種
等價
關系——因為我們可以理直氣壯地說
圓就是一種幾何形狀
為了對繼承進行測試
一個辦法就是看看自己是否能把它們套入這種
等價
關系中
看看是否有意義
但在許多時候
我們必須為衍生類型加入新的接口元素
所以不僅擴展了接口
也創建了一種新類型
這種新類型仍可替換成基礎類型
但這種替換並不是完美的
因為不可在基礎類裡訪問新函數
我們將其稱作
類似
關系
新類型擁有舊類型的接口
但也包含了其他函數
所以不能說它們是完全等價的
舉個例子來說
讓我們考慮一下制冷機的情況
假定我們的房間連好了用於制冷的各種控制器
也就是說
我們已擁有必要的
接口
來控制制冷
現在假設機器出了故障
我們把它換成一台新型的冷
熱兩用空調
冬天和夏天均可使用
冷
熱空調
類似
制冷機
但能做更多的事情
由於我們的房間只安裝了控制制冷的設備
所以它們只限於同新機器的制冷部分打交道
新機器的接口已得到了擴展
但現有的系統並不知道除原始接口以外的任何東西
認識了等價與類似的區別後
再進行替換時就會有把握得多
盡管大多數時候
純替換
已經足夠
但您會發現在某些情況下
仍然有明顯的理由需要在衍生類的基礎上增添新功能
通過前面對這兩種情況的討論
相信大家已心中有數該如何做
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26315.html