1. 程式人生 > >php 多繼承和弊端 && 順位的trait

php 多繼承和弊端 && 順位的trait

轉載文章  http://blog.csdn.net/batoom/article/details/6052565

trait       http://php.net/manual/zh/language.oop5.traits.php

總結:
    

    php  多繼承的是很混亂的,二義性和Diamond of  Death  兩頭小中間大的繼承樹

            所以使用trait 替代(清晰明瞭, 實現了複用程式碼,扁平化的方式 更加清晰, 解決了二義性(需要執行使用什麼方法不然報錯)

昨天晚上和G討論一個問題是否使用多重繼承的問題,當時我是極力反對,因為多重繼承在我的影響中式極差的,認為這是一個應該讓人唾棄的。主要原因是我認為它十分容易引起各種各樣的混亂,程式設計上的和設計上的。 但對於它具體情況並不是很瞭解,因為我重來沒有用過多重繼承,這是因為考試的原因,瞭解過這個東西,考完了馬上就丟掉了。為了具體瞭解這個東西,我上網百度了下,找到了大眾對於它的評論。 優點: 對於它的優點,是顯而易見的,簡單,清晰,更有利於複用。雖然單一繼承也能有利於複用,但是還是有可能有很多的重複程式碼。如果使用了多重繼承,重複程式碼會減少很多。比如百度百科裡提到了一個例子,一隻貓,可以同時繼承於哺乳類和卡通類,這樣就不用再去重新寫卡通類的屬性和方法。 缺點: 缺點也很明顯,首先是二義性,兩個基類中有同名方法的時候,你不得不在子類的呼叫中指明此方法出自那個基類。這看起來有些麻煩,幸好在你迷糊的時候,編譯器會提醒你。其次:假如類A派生了B和C,而B和C共同派生了D,麻煩就出現了。這種中間大兩頭小的繼承樹有個形象的名字:鑽石型繼承樹(DOD:Diamond Of Death)。從“Death”字面看這是個非常不好的單詞,事實也如此,A是D的父類,但是有兩條路徑。這樣的資料組織方式會有一些難以預料的後果。除去二義性不說,想想吧,D中有多少個看似重複的方法,有多少個名字相同的資料成員! “ 不惜一切代價,避免DOD的出現。除非,你認為DOD出現在這裡是最恰當不過的,而且,確保你你使用了虛基類(虛繼承),確保你對每個類的細節都完全清楚,確保你知道虛基類(虛繼承)的副作用。 ” 這裡再引進一個詞彙,vtable(c++裡的,PHP有沒有不是很清楚,沒有百度到,不過應該有吧。) Vtable   虛表。   每一個有虛擬函式的類都有這樣一個東西。   它實際上記錄了本類中所有虛擬函式的函式指標,也就是說是個函式指標陣列的起始位置。   比如virtual void TheSecondFun()記錄在陣列的第二個元素,當一個該類的物件例項呼叫TheSecondFun時就根據對應關係把第二個函式指標取出來,再去執行該函式,這種行為叫晚繫結,也就是說在執行時才知道呼叫的函式是什麼樣子的,而不是在編譯階段就確定的早繫結。多重繼承還會使得子類的vtable變得不同尋常。單繼承的vtable只是在父類vtable的表尾加上新的虛擬函式,子類物件的vtable中包含了有序的父類vtable。而對於多重繼承,兩個父類可能有完全不同的vtable,因此,子類的vtable中絕對不可能包含完整的有序的兩個父類的vtable。子類的vtable中可能包含了兩塊不相連的父類vtable,因此每個父類都被迫追加了一個vtable,也就是,每個父類的物件都添加了一個指標。 多重繼承還會帶來一些其他的問題:使用父類指標指向子類物件變成了一件複雜的事情。你不得不用到C++中提供的dynamic_cast來執行強制轉換。至於dynamic_cast,也是個麻煩的傢伙,它是在執行期間而非編譯期間進行轉換的(因為編譯期間它不能確定到底要轉向一個什麼型別),因此除了會帶來一些輕微的效能損失,它要求編譯器允許RTTI(Runtime Type Information,執行時型別資訊),也就是要求編譯器儲存所有類在執行時的資訊。 總結下:實際生活中,一些事物往往會擁有兩個或兩個以上事物的屬性,為了解決這個問題,引入了多重繼承的概念。 多重繼承的優點是物件可以呼叫多個基類中的介面。 多重繼承的缺點是容易出現繼承向上的二義性,並且增加了程式的複雜度。 建議: 明智而謹慎地使用多重繼承 Use multiple inheritance judiciously. 最後的最後:存在即合理吧。