物件導向雜感

2021-09-06 04:31:26 字數 2308 閱讀 1713

最近發現乙個物件導向比較有趣的討論:談談繼承的侷限性(

以四邊形,矩形,正方形為例子討論繼承的問題。矩形是兩對邊平衡的四邊形,而正方形是內角為90度的矩形。

一種設計方式是:四邊形做基類,矩形繼承自四邊形,正方形繼承自矩形。理由是:矩形是四邊形,正方形是矩形。矛盾在於,物件導向的類繼承隱喻了這樣一件事:子類是父類的超集(包含父類),但是正方形並不需要四條邊長的屬性,而只需要一條邊長(因為4條都一樣),也就是正方形反而比四邊形要小。

這種說法貌似挺有道理,也是我們設計中可以借鑑的。但是認真思考一下,反而覺得不是那麼明確。

我想要解決這個問題,應該從根本上對繼承進行深入的解剖。繼承隱喻了子類是父類的超集這一技術特徵,因此省去編碼的麻煩,他等價於把父類作為子類成員。

如:class 正方形

四邊形 base;

我們很容易發現問題是我們完全不需要四邊形來實現正方形,我們只需要乙個int成員就能夠實現正方形。繼承的問題在於繼承強制性的決定了子類只包含父類,而這種假定的目的僅僅是為了形成繼承關係,也就是多型(通用訪問介面)。這其實只需要通過介面便可以完美的解決。

繼承和介面的分別就是介面不限制實現,你可以用任何方式實現子類。繼承本身不但包含了介面,還包含了資料定義等屬於實現細節的內容。

我認為,繼承是不完全的物件導向技術,因為物件導向最重要的內容就是隱藏實現,隔離外部和內部,實現多型訪問,但是繼承會讓同乙個繼承族的類之間無法做到這一點。

如果讓我設計物件導向語言,我會讓類自身無法訪問,而只能通過介面訪問。類負責實現細節,介面負責訪問介面。

如果按照介面的角度去設計這三個物件,我們只會得到乙個介面,那就是「可計算面積的多邊形」,然後包含乙個統計面積的函式。使用者的最終目的是面積,而什麼邊長、角度之類的都只是細節罷了。

可見,介面才是為使用者服務的,而繼承只是一種不成功的設計模型,他是為細節實現服務的一種自以為高明的正規化。繼承會讓你認為只要不斷地擴充套件子類,就能設計出乙個完美的系統,它基於一種似是而非的推理邏輯:子類是父類的超集,這種「是」關係很常見,而現實是這種模型並不常見。人們說的「是」,大多數情況都不是一種子集和超集的關係,反而是一種更加反叛的,對父類否定和修改的模型。

我上面談到模型的問題,現實問題中會出現哪些模型,下面歸類一下。

子集超集關係:繼承就是基於這種關係的設計正規化。但是組合是更好的方式,因為組合可以替換成員的實際型別,繼承卻不可以。用「子類是父類」這種語言大多數情況是無法產生正確的設計,需要用「子類有成員」這樣的語言去推理。

原型和特例的關係:這是比較常見的情況。大多數物件都有乙個共同的原型,但是大多數都需要經過一些修正才能符合需求。

無關係:沒有共同點的物件。

注意!這裡說的是實現細節的問題,而介面不參與實現細節,所以是屬於不同範疇的話題。

和物件導向相對的另乙個設計哲學就是泛型,泛型是引數化的型別。事實上,引數化是乙個很通用的技巧,比如函式的引數化,乙個函式依賴引數,而不是依賴具體資料,這樣便可以得到通用的演算法。

我把方法進行了一些歸類:

過程:乙個**片段

函式:乙個演算法

泛型函式:乙個通用演算法

可見,引數化的目的是得到更加通用的演算法。

引數化型別的目的也是類似的,為了得到乙個更加通用的型別。對設計物件而言,成員就是其引數。如果不對成員進行引數化,那麼這個物件就是死板的。筆者有乙個不太成熟的想法,通過建構函式傳遞物件的引數,這個引數實際就是初始化成員,而成員由方法使用,這就得到了乙個通用的物件。

至於引數化成員的多少與相對重要性等問題,和方法的使用情況有關,如果該成員構成物件的本質屬性,他就應該引數化。比如汽車的引擎就應該引數化,至於顏色之類的關係不大的可以無需引數化。

筆者認為,乙個成功的物件導向設計,應該正確處理介面和實現的關係(通過介面而不通過類訪問物件),應該避免使用繼承(通過使用組合和介面替代),應該更加的通用(引數化關鍵成員)。

有些時候,成員沒有使用其他型別,而方法裡面卻使用了其他型別,這更加糟糕,因為方法硬編碼呼叫了其他型別,會產生更加緊密的耦合,改進的方法是把它作為成員,或者把他做為方法引數。至於什麼時候應該作為成員,什麼時候應該作為方法引數,筆者暫時還不能提供建議。

物件方法分析細節:

1.過程,無引數

2.過程,無引數,呼叫成員

3.過程,無引數,呼叫成員,建立外部物件

4.函式,有引數

5.函式,有引數,呼叫成員

6.函式,有引數,呼叫成員,建立外部物件

對於物件設計來說,如果不呼叫成員,那麼大可以作為類成員,而不是物件成員來實現。如果乙個過程,不呼叫外部成員,那麼他就是乙個固定的沒有變化的函式。如果它是乙個函式,它就是乙個純粹的工具演算法,和型別無關,不如把它移出去並進行通用化。

乙個普通的方法,應該是那些呼叫成員的方法。乙個劣質的方法,是那些建立物件的方法,因為這會增加方法對外部型別的依賴。

物件導向 初識物件導向

面向過程思想 步驟清晰簡單,第一步做什麼,第二步做什麼.面向過程適合處理一些較為簡單的問題 物件導向思想 物以類聚,分類的思維模式,思考問題首先會解決問題需要分哪些類,然後對這些類進行單獨思考,最後才是對某個分類下的細節進行面向過程的思索 物件導向適合處理複雜的問題,適合處理需要多人協作的問題 對於...

秋天的雜感

關於專案管理 如果不真正實際的而去管理專案,僅憑理論是無法學會專案管理的。看著別人管的簡單,真正自己管的時候往往就覺得無從下手。大音稀聲,大象無形,專案管理決無定式,也無最佳實踐。世間本來沒有路,走的人多了就成了路,失敗往往就是交學費,多實踐和積累了就有了相關的方 關於聽取不同意見 我一直希望自己有...

物件導向程式設計01 面向過程 物件導向

前面12講我已經寫完了從零開始學j ase 慶祝完結撒花!那麼從今天開始正式步入物件導向程式設計。建議開啟本章之前先回顧 j ase010方法詳解和 j a變數與方法的呼叫 同類操作中與跨類操作中的對比 物件導向程式設計 oop object oriented programming 物件導向程式設...