物件導向思想的理解

2021-07-11 15:04:58 字數 3019 閱讀 5508

物件導向方法被人談論了二十多年了。我接觸它比較晚,直到九十年代中期才開始學習使用它。若說對這個方法做些評價,那還真是大言不慚了。不過這麼些年來,也週期性的對物件導向做些思考。或對或錯,我想都值得總結一下。一家之言,來看的同學不必太當真。

首先我們要區分一下「基於物件」和「物件導向」的區別。

基於物件,通常指的是對資料的封裝,以及提供一組方法對封裝過的資料操作。比如 c 的 io 庫中的 file * 就可以看成是基於物件的。

物件導向,則在基於物件的基礎上增加了多型性。所謂多型,就是可以用統一的方法對不同的物件進行同樣的操作。當然,這些物件不能完全不同,而需要有一些共性,只有存在了這些共性才可能用同樣的方法去操作它們。我們從 c++ 通常的實現方法的角度來看,a 和 b 在繼承關係上都有共同的祖先 r ,那麼我們就可以把 a 和 b 都用對待 r 的控制方法去控制它們。

為什麼需要這樣做?

回到乙個古老的話題:程式是什麼?

程式 = 演算法 + 資料結構

在計算機的世界裡,資料就是乙個個位元的組合;**的執行流程就是順序、分支、迴圈的程式結構的組合。用計算機解決問題,就是用程式結構的組合去重新排列資料的組合,得到結果。為了從龐大的輸入資料(從 bit 的角度上看,任何輸入資料都可能非常的龐大),通過**對映到結果資料。我們就必須用合理的資料結構把這些位元資料組合起來,形成數量更少的單元。

這些單元,就是物件。物件同時也包括了對它進行操作的方法。這樣,我們完成了一次封裝,就變成了:

程式 = 基於物件操作的演算法 + 以物件為最小單位的資料結構

封裝總是為了減少操作粒度,資料結構上的封裝導致了資料資料的減少,自然減少了問題求解的複雜度;對**的封裝使得**得以復用,減少了**的體積,同樣使問題簡化。

思考:物件導向,輸入輸出,物件只要關注輸入和輸出就可以了,中間怎麼變化,我們都不管,我們只管用,面向的物件就是我們了,我們就是物件。

高質量的**是 指可調整(scalable)、 模組化(modular)、可 復用(reusable)、 可擴充套件(e xtendable) 且簡單(******)(簡稱smores)的代 碼。

接下來來看 基於物件操作的演算法。這種演算法必須將操作物件看成是同樣的東西。在沒有物件的層次上,演算法操作的都是位元組,是同類。但是到了物件的層次,就不一定相同了。這個時候,演算法操作的是乙個抽象概念的集合。

在物件導向的程式設計中,我們便少不了容器。容器就用來存放一類有共同抽象概念的東西。這裡說有共同概念的東西,而沒有說物件。是因為對於演算法作用於的集合,裡面放的並不是物件實體,而是乙個對實體的引用。這個引用表達的是,演算法可以對引用的那一頭的東西做些什麼,而並不要求那一頭是什麼。

比如,我實現乙個 gui 系統(或是乙個 3d 世界)。需要實現乙個功能——判斷滑鼠點選到了什麼物件。這裡,每個物件提供了乙個方法,可以判斷當前滑鼠的位置有沒有捕獲(點到)它。

這時最簡單的時候方法是:把所有可以被點選的物件都放在乙個容器中,每次遍歷這個容器,檢視是哪乙個物件捕獲了滑鼠。

我們並不需要可被點選的物件都是同類,只需要要求從容器中可以以統一方法訪問每個元素的是否捕獲住滑鼠的這個判定方法。

也就是說,把物件置入容器時,只需要讓置入的東西有這乙個判定方法即可。了解 com 的同學應該明白我要說什麼了。對,這就是 queryinte***ce 的用途。com 的 query inte***ce 就是說,從乙個物件裡取到乙個特定可以做某件事情的介面。通常接下來的**會把它放在乙個容器裡,方便別處的**可以幹這些事情。

物件導向的本質就是讓物件有多型性,把不同物件以同一特性來歸組,統一處理。至於所謂繼承、虛表、等等概念,只是實現的細節。

說到這裡,再說一下 com 。com 允許 介面繼承 ,但不允許介面多繼承。這一點是從二進位制一致性上來考慮的。

為什麼沒提 實現繼承 的事情?因為實現繼承不屬於物件導向的必要因素。而且,現在來看,實現繼承對軟體質量來說,是有負面影響的。因為如果你改寫基類的虛方法,就意味著有可能破壞基類的行為(繼承角度看,基類物件是你這個物件的一部分)。往往基類的實現早於派生類,並不能了解到派生類的需求變化。這樣,在不了解基類設計的前提下,冒然的實現繼承都是有風險的。這不利於軟體的模組化分離和元件復用。

但是介面繼承又有什麼意義呢?以我愚見,絕大多數情況下,同樣對設計沒有意義。但具體到 com 設計本身,讓每個介面都繼承於 iunknown 卻是有意義的。這個意義來至於基礎設施的缺乏。我指的是 gc 。在沒有 gc 的環境中,addref 和 release 相當於讓每個物件自己來實現 rc (引用計數)的自動化管理。對於非虛擬機器的原生**,考慮到 com 不依賴具體語言,這幾乎是唯一的手段。另外 com 還支援 apartment 的概念,甚至允許 com 物件處於不同的機器間,這也使得 gc 實現困難。

queryinte***ce 存在於每個 com 介面中卻有那麼一點格格不入。它之所以存在,是因為 com 介面指標承擔了雙重責任,既指出了乙個抽象概念,又引用了物件的實體。但從乙個具體演算法來看,它只需要對一組相同的抽象概念做操作即可。但它做完操作後,很可能(但不是必須)需要把物件放入另乙個不同的集合中,供其它演算法操作。這個時候,就需要 queryinte***ce 將其轉換為另外乙個介面。

如果去掉了 addref release (依賴 gc )以及 queryinte***ce (只在需要時增加乙個介面獲得物件的引用),iunknown 就什麼都不剩了。那麼介面繼承也完全不必存在。

回頭再來看程式語言。

c++ 提供了對物件導向的支援,但 c++ 所用的方法(虛表、繼承、多重繼承、虛繼承、等等)只是一種在 c 已有的模型上,追加的一種高效的實現方式而已。它不一定是最高效的方式(雖然很少能做到更高效),也不是最靈活的方式(可以考察 ruby )。我想,只用 c++ 寫程式的人最容易犯的錯誤就是認為 c++ 對物件導向的支援的實現本身就是物件導向的本質。如果真的理解了物件導向,在特定需求下可以做出特定的結構來實現它。語言就已經是次要的東西了。

了解你的需求,區分我需要什麼和我可以做到什麼,對於設計是很重要的。好的設計在於減無可減。

你需要物件導向嗎?你需要 gc 嗎?你需要所有的類都有乙個共同的基類嗎?你需要介面可以繼承嗎?你為什麼需要這些?

物件導向思想 談談你對物件導向的理解

物件導向程式設計,即oop,物件導向的概念和應用已經超越了程式設計 軟體開發領域,現在已經發展到了各個領域。物件導向可以說是對現實世界理解和抽象的方法,是計算機程式設計技術發展到一定階段的產物。它的特點 抽象 封裝 繼承 多型 用我的話說,其實可以這麼理解,假如我是上帝,我要造 人 這是物件 首先,...

談談對物件導向思想的理解

這個問題,通常會讓很多人有點不知所措,感覺我一直在編碼,但是說到思想很難去闡述。下面,我說說自己的想法,首先,談談 面向過程 vs 物件導向 所以,物件導向的思維更多的是考慮如何去選擇合適的工具,然後組織到一起幹一件事。好比乙個導演,要拍一場電影,那麼首先要有男豬腳和女豬腳,然後還有其他等等,最後把...

物件導向的思想

物件導向的好處 1.物件導向是一種更符合人們思考習慣的一種思想 2.面向過程的更多體現是執行者 物件導向更多體現的是指揮者 3.有了物件導向這個事情後 複雜問題就簡單化了 大西瓜如何用挖掘機炒菜?幾個事物 2事物 大西瓜 name age 屬性 行為 會開挖掘機 挖掘機 color lunzi 翻炒...