多數好的設計者象躲避瘟疫一樣來避免使用實現繼承(extends關係)。實際上80%的代碼應該完全用interfaces寫,而不是通過extends。「Java設計模式」一書詳細闡述了怎樣用介面繼承代替實現繼承。下面學步園小編來講解下為什麼在Java編程中的繼承多數是有害的?
為什麼在Java編程中的繼承多數是有害的
Extends是有害的;也許對於CharlesManson這個級別的不是,但是足夠糟糕的它應該在任何可能的時候被避開。「JAVA設計模式」一書花了很大的部分討論用interface繼承代替實現繼承。
好的設計者在他的代碼中,大部分用interface,而不是具體的基類。本文討論為什麼設計者會這樣選擇,並且也介紹一些基於interface的編程基礎。
介面(Interface)和類(Class)?
一次,我參加一個Java用戶組的會議。在會議中,JamsGosling(Java之父)做發起人講話。在那令人難忘的Q&A部分中,有人問他:「如果你重新構造Java,你想改變什麼?」。「我想拋棄classes」他回答。在笑聲平息後,它解釋說,真正的問題不是由於class本身,而是實現繼承(extends)關係。介面繼承(implements關係)是更好的。你應該儘可能的避免實現繼承。
失去了靈活性
為什麼你應該避免實現繼承呢?第一個問題是明確的使用具體類名將你固定到特定的實現,給底層的改變增加了不必要的困難。
在當前的敏捷編程方法中,核心是並行的設計和開發的概念。在你詳細設計程序前,你開始編程。這個技術不同於傳統方法的形式----傳統的方式是設計應該在編碼開始前完成----但是許多成功的項目已經證明你能夠更快速的開發高質量代碼,相對於傳統的按部就班的方法。但是在並行開發的核心是主張靈活性。你不得不以某一種方式寫你的代碼以至於最新發現的需求能夠儘可能沒有痛苦的合併到已有的代碼中。
勝於實現你也許需要的特徵,你只需實現你明確需要的特徵,而且適度的對變化的包容。如果你沒有這種靈活,並行的開發,那簡直不可能。
對於Inteface的編程是靈活結構的核心。為了說明為什麼,讓我們看一下當使用它們的時候,會發生什麼。考慮下面的代碼:
f()
{
LinkedListlist=newLinkedList();
//...
g(list);
}
g(LinkedListlist)
{
list.add(...);
g2(list)
}
假設一個對於快速查詢的需求被提出,以至於這個LinkedList不能夠解決。你需要用HashSet來代替它。在已有代碼中,變化不能夠局部化,因為你不僅僅需要修改f()也需要修改g()(它帶有LinkedList參數),並且還有g()把列表傳遞給的任何代碼。象下面這樣重寫代碼:
f()
{
Collectionlist=newLinkedList();
//...
g(list);
}
g(Collectionlist)
{
list.add(...);
g2(list)
}
為什麼在Java編程中的繼承多數是有害的
這樣修改Linkedlist成hash,可能只是簡單的用newHashSet()代替newLinkedList()。就這樣。沒有其他的需要修改的地方。
作為另一個例子,比較下面兩段代碼:
f()
{
Collectionc=newHashSet();
//...
g(c);
}
g(Collectionc)
{
for(Iteratori=c.iterator();i.hasNext())
do_something_with(i.next());
}
和
f2()
{
Collectionc=newHashSet();
//...
g2(c.iterator());
}
g2(Iteratori)
{
while(i.hasNext())
do_something_with(i.next());
}
g2()方法現在能夠遍歷Collection的派生,就像你能夠從Map中得到的鍵值對。事實上,你能夠寫iterator,它產生數據,代替遍歷一個Collection。你能夠寫iterator,它從測試的框架或者文件中得到信息。這會有巨大的靈活性。
以上就是關於「為什麼在Java編程中的繼承多數是有害的」的內容,希望對大家有用。更多資訊請關注學步園。學步園,您學習IT技術的優質平台!