1. 程式人生 > >java如何繼承兩個類?以及討論一下多繼承的利弊。

java如何繼承兩個類?以及討論一下多繼承的利弊。

多重繼承是一件很複雜、很容易產生問題的功能。它跟Goto語句一樣,利弊交織。 以下分兩部分敘述,第一部分是Python多重繼承遇到的麻煩,第二部分是Java和Ruby如何折中多重繼承需求。 ============================================ 第一部分: Python是支援多重繼承的,但為了解決多重繼承的方法查詢順序問題(被稱為MRO),有一場苦難史: 1. 傳統模式 直接使用深度優先演算法(並且,從左向右),每個類選擇其第一次出現的位置。比如
class A:
  def save(self): pass
class B(A): pass
class C:
  def save(self): pass
class D(B, C): pass
作為D類的一個例項,它的成員尋找順序是:D、B、A、C。
但當碰到如下這樣一個“菱形繼承”就麻煩了:
class A:
  def save(self): pass
class B(A): pass
class C(A): def save(self): pass class D(B, C): pass
作為D類的一個例項,尋找順序也是D、B、A、C,但呼叫其save方法時,到底是呼叫A中的呢?還是C中的呢?直觀上看,應該是C。這裡有產生矛盾了。
2. Python2.2的new-style class模式
Python2.2中引進了new-style class,說白了就像java一樣,所有類都繼承自最根本的object類。
這就讓“菱形繼承”變成十分普遍,於是只能改變MRO策略。
仍然使用深度優先搜尋、從左向右,但是每個類選擇其最後一次出現的位置。
這樣一來,對上面的“菱形繼承”就處理比較完美了,形成的順序是:D、B、C、A,越是公用基礎類,越放在後面。
但是,碰到交叉繼承
,就又懵了。
<img src="https://pic4.zhimg.com/d067bccb353065c3276a96f6aab93a77_b.jpg" data-rawwidth="113" data-rawheight="179" class="content_image" width="113">這裡,X和Y都繼承自O,A繼承(X,Y)(注意,有先後順序),B繼承(Y,X),再有個最下面的類繼承(A,B)。
這裡,X和Y都繼承自O,A繼承(X,Y)(注意,有先後順序),B繼承(Y,X),再有個最下面的類繼承(A,B)。
按照上述演算法出來的結果是:?、A、B、Y、X、O。這就有些奇怪了,明明A在B前,A繼承的X在Y前,可為啥X的優先順序比Y要低呢?
3. C3演算法
1996年,一幫牛人寫了一篇文章A monotonic superclass linearization for Dylan,提供了一個基於層級計算的線性MRO演算法,被稱為C3,整體上比較合理了。(演算法不詳說了)
在2012年被加入了Dylan語言,2007年加入了Python2.3,此外還有Perl 6、Parrot等語言之中。
這樣雖說基本解決了計算問題,但多重繼承本身就有很多讓人疑惑的地方,比如:
<img src="https://pic4.zhimg.com/c1e6e9a3a1df789b9686582a9367326b_b.jpg" data-rawwidth="251" data-rawheight="171" class="content_image" width="251">參考文獻:參考文獻:
python-history.blogspot.jp
The Python 2.3 Method Resolution Order
============================================
第二部分:
多重繼承那麼複雜,可單一繼承又那麼拘束,咋辦呢?
1. 介面繼承
Java就是那麼做的,只允許單一繼承類(方法的實現),但可以繼承多個介面(方法的定義)。
Java的介面繼承功能,既實現了靜態語言的多重繼承性,又避免了多重繼承的資料構造的衝突和類層次的複雜性。
但是,我們並不能說介面是解決問題的完美方案。介面也有不能共享實現的缺點。
本來只是為了跨越繼承層次來共享程式碼,現在卻需要另外生成一個獨立物件,而且每次方法呼叫都要委派給這個物件,這實在是不太合理,而且執行的效率也不高。
——《松本行弘的程式世界》
2. Mix-in
這是Ruby所推崇的,最初在Lisp中開始使用。規則如下:
  1. 通常的繼承都是單一繼承。
  2. 第二個以及兩個以上的父類必須是Mix-in的抽象類(即不能單獨生成例項,不能繼承普通類)。
這種規則下,既能夠保持單一繼承的結構,又能用Mix-in來共享方法的實現。