為何少部分語言如C++和python要堅持引入多繼承?
01-27
記得BS好像在《C++程序設計語言》中多繼承這一章,給了一個前言,一句話:「因為你有父親和母親。」
多繼承的問題在於程序員的濫用,C++雖然支持,但我碰到的很多項目都是通過代碼規範來規定只能用多繼承實現介面的功能,java這種相當於幫你強制規範了,反過來說要在java實現「多繼承」,繞繞彎子也能做到的C++之父說過,他特別討厭語言設計者將自己的習慣強加給使用者,於是C++就支持了很多特性,至於用不用就看你了,不是說有了就一定用,很多時候是非常推薦只用它的一個子集的,從這個角度說,雖然多繼承有問題且很多時候沒必要用,就算非要用也能繞開,但C++就是畢竟提供了,這是一個設計哲學問題了:簡單說就是,為啥有,因為作者想有唄
為何部分語言如java要堅持不引入多繼承
每次想用多繼承,都會先考慮是不是該重構了。
我覺得「堅持引入多繼承」並不是正確的說法,因為在C++誕生的那個年代,很多特性都帶有試驗性的,並沒有「堅持引入」一說,因為C++的歲數比現在流行的大多數OO語言實在要大得多了。再說多重繼承這個東西吧,既不能說是個什麼C++的優勢,也不能說是它的缺陷,只能說是個特色。某些技術,比如微軟的COM就是通過多重繼承實現的,這證明了多重繼承的實際價值(當然後來COM也像所有微軟的其它技術一樣遭人病垢,微軟就是這麼遭人恨,我也沒辦法),所以你你至少不能否認多重繼承的意義,但是正如C++的很多其它特性一樣,用不好多重繼承的人總是對多重繼承多有指責,這是沒有道理的。面對一種技術,首先你要明白它的實際價值,才好去從反面對它進行批評。歷史上很多C++同期的技術都退出宇宙了,但是C++仍然保持了旺盛的生命力,這是有道理的。當然,這裡我扯的有些遠了,你是在談論多重繼承,而不是C++本身,但是我認為這都是一樣的。
對Python不熟,下面只討論C++的多重繼承。
多重繼承是個好東西,並不是因為歷史原因而被保留下來的語言闌尾。
1、多重繼承的例子在現實世界中隨處可見。如果程序設計語言支持多重繼承,則可以用最直接、最自然的方式對其進行抽象和映射。
2、C++相信:不可能通過減少語言特性來增強語言的表達力。
3、濫用多重繼承的確會導致很大問題,但這是程序員自己的能力問題,與C++無關。
4、C++優先照顧的是專家程序員的需求,而不是新手程序員的需求。因為多繼承是一種很有用的特性,沒有該特性的語言會令人感到一點不便。所以真正的問題是其它語言為什麼不支持該特性,僅僅說因為容易被少部分欠缺經驗的人誤用顯得很沒說服力。
引入多繼承你可以不這樣做啊,照樣單繼承不就好了,又不是強迫你非得多繼承。但是如果強制單繼承可就沒法多繼承了。
一般沒有多繼承功能的語言會用其他方法實現類似功能。如Java的interface,ruby的mixin.所以,多繼承或者類似多繼承是為了寫出更好代碼的一種範式,但是不同語言會有不同的支持這種範式的實現方法。
多繼承本身沒多大問題 最大的弊端還是在於濫用吧比如Python的多繼承在工程上主要體現於mixin 算是一種折中的做法而Java在JDK8中也給interface加入了defaut方法 算是間接承認了多集成的必要性
csharp,py,ruby,java,scala,golang。為何我了解的這些語言都有多繼承?!mixin是很實用的東西,不是異類
語言支持多繼承沒有什麼不妥。又沒有強制你使用多繼承。規範是死的,人是活的。
濫用多繼承不對,教條的不使用多繼承也是不對的。
多繼承難道不是一種極度自然的特性嗎?難道不覺得只有interface是一種不正常的閹人嗎?
有幾個人,在所謂的軟體行業,加班加得很high,因為久坐不動導致下肢靜脈血栓,被迫截肢。他們覺得自己很正常,這是因為整天加班著,看到的都是幾個同樣被截肢的同事。一天,他們被公司裁員了。無事上街,一看,這還得了,拉住一個健康的晨跑的小夥子,疑惑地問到:「你們為何堅持不將腿割掉?」1. 以前 C++ 中沒有明確的 interface (不確定現在有沒有), 多重繼承可以用來實現 interface.2. 在使用某些容器類型時, 比如鏈表和樹, 節點必須是引用類型. 如果不能多重繼承, 那麼只能以包含節點對象的方式使用容器. 一方面代碼變得不直觀, 另一方面堆對象數量多了一倍. C# 的 LinkedList 是個典型的例子.3. 在某些開發環境中, 你必須繼承某些 API 提供的內置類來定製自己的類, 這意味著你不能修改這些內置類. 這時如果需要自己的類具備其他類的特徵時, 你不得不使用"不優雅"的方式解決問題 (更麻煩的情況是, 你想要繼承的兩個類都是不可修改的, 甚至沒有源碼).4. 最近我有個需求是, B 類和 C 類都具有 A 類的特徵且除此之外沒有共同點; 後來又需要一個 D 類同時具有 B 類和 C 類的特徵. 因為使用 C# 不能使用多重繼承, 這時再次想念 C++ 的好了.
JS在這裡就不知高到哪去了
多繼承非常自然啊,繼承了1萬個類,就能轉成一萬個類的指針,太靈活了,千變萬化!!!
就我的理解,這和歷史上一種叫鴨子類型機制的泛型機制有關,鴨子類型機制現在被廣泛用於動態語言中
這種機制的核心在於,只要某個事物會飛,就認為這是鴨子,可以調用屬於「鴨子」所有方法
這件事物能不能同時是另一種東西呢?能不能是食物呢?能不能是水呢?完全可以,鴨子類型機制不關心具體類型,只關心是否提供了方法這是不是和Java中介面的概念有點像呢,通過介面,我們可以打破類家族的界限,不在關心類型,而是把注意力集中在介面上(此處的介面不能認為是Java中的interface),這樣,我們獲得了比多態更低的耦合性,因為我們實際上採用的是**面向介面編程**
而interface的設計只是多繼承中的一種,目的都是方便解耦多繼承是介面,別拿來干介面以外的事情就行了
推薦閱讀:
※Smalltalk 的 Live Programming 是怎樣實現的?
※面向對象在數值計算中如何應用,有哪些具體例子,相較普通函數能夠多大程度提高計算效率?
※面向對象(一)|面向對象概念及優點(以py為例)
※MATLAB高級數據結構連載5: table 2