一、面向對象概念的一些誤解
“面向對象”是一個如今被人叫爛的詞匯,就像去年人們都喜歡把自己的公司打上“.com”的標記一樣。其實有多少人能真正理解這個詞匯呢,很難說。我喜歡這樣來比喻人們對“對象”一詞的濫用。“對象”就好比人們經常說的“酷”和“爽”,很多人並不仔細考慮這兩個詞的差別,在很多情況下他們是通用的,“酷”和“爽”通常表達“心情不錯”的意思,你可以在你玩的興奮的時候,大聲的叫嚷“太酷了,太爽了”,這個時候兩個詞匯是通用的。但是你可以說“這個人很酷啊”,但是你不能說“這個人很爽啊”。人們對“對象”這個詞匯的濫用就發生在這裡,“面向對象”和“基於對象”就好比“酷”和“爽”,這是兩個不同的概念,但是人們通常將這兩個詞匯混為一談,一律用“面向對象”來表達。常見的錯誤可以在此列舉一些:
1)有個人興高采烈的和你說“我不喜歡 flash 4 的腳本語言,flash 5 版本的 action script 采用了新的面向對象的“.”語法,寫起來很舒適。我現在一直用 flash 5 來做東西。”(同樣的話語也發生在 Director 的 lingo 腳本語言中)
2)visual basic 采用了面向對象的屬性和方法,比起過去的 basic 語言有了很大的提高。
3)javascript 是面向對象的。
等等。
通常聽到類似的話,你都要認真審閱說話之人,分析他說的話。可以肯定一點,他並非真正懂得什麼是面向對象的思想。很多人沒有區分“面向對象”和“基於對象”兩個不同的概念。面向對象的三大特點(封裝,繼續,多態)卻一不可,通常“基於對象”使用對象,但是無法利用現有的對象模板產生新的對象類型,繼而產生新的對象,也就是說“基於對象”沒有繼續的特點,而“多態”是表示為父類類型的子類對象實例,沒有了繼續的概念也就無從談論“多態”。現在的很多流行技術都是基於對象的,它們使用一些封裝好的對象,調用對象的方法,設置對象的屬性。但是它們無法讓程序員派生新對象類型。他們只能使用現有對象的方法和屬性。所以當你判定一個新的技術是否是面向對象的時候,通常可以使用後兩個特性來加以判定。“面向對象”和“基於對象”都實現了“封裝”的概念,但是面向對象實現了“繼續和多態”,而“基於對象”沒有實現這些,的確很饒口。
二、Java 比 C++ 在貫徹面向對象的思想方面更加徹底。
我最近上的學習班的老師對我說:“C++ 是打著面向對象的幌子,干著過程編程的勾當”,這句話我非常的贊同,而且我一直以來也是這麼認為的。但是仔細聽他講解後,我才發現,我是只是理解了這句話前兩層的意思。但是還有一層意思我沒有理解。你可能要問,“難道 C++ 不是面向對象的嗎?”。事實上 C++ 是真正的面向對象編程語言。但是它也是過程編程語言。為什麼怎麼說呢, C++ 的產生不但考慮了面向對象的特性,而且也更多的考慮了對 C 語言的向後兼容,使得 C++ 這種雜合語言表現出“過程”和“對象”編程的雙重性。你通常既可以繼續用 C++ 編譯器來編寫傳統的 C 程序,也可以使用 C ++ 的類庫或者編寫自己的類來作面向對象編程。這種“兩面性”使得人們可以繼續保留原有的 C 代碼,同時也阻礙了面向對象思想的推廣。
舉個簡單的例子,94 年的時候,我開始學習 C++ ,當時是學習 turbo C++ 自己帶的一個叫作 turbo vision 的類庫來做項目。我的同學也用 turbo C++ ,但是他一點也沒有學習過 C++ 這個語言,他只是用 turbo c++ 編譯器來重新編譯他以前用 turbo c 寫的程序,然後他自豪的對我說:“瞧,我用 c++ 做的東西”,似乎意思是說“我用 c++ 開發項目了”,在那個 c 比 pascal 高檔, pascal 比 foxbase 高檔的年代裡, C++ 的標簽絕對是個很"酷"的標志。我其實很清楚他的行為。這就是“C++ 是打著面向對象的幌子,干著過程編程的勾當”的第一重意思,也就是說, C++ 編譯器對 C 程序的兼容性造成了最底層的“過程勾當”。在國內有很長一段時間,人們都是在用 C++ 編譯器做 C 編程。 我當時在想,比起我那個同學,我才是真正懂得面向對象的人。 我學習了 C++ 語言,我懂得封裝,繼續和多態,我學習了 turbo vision 的類庫,我派生了 turbo vision 的類庫並編寫了自己的類,所以我是懂得面向對象的。從某種意義上說,我這麼想是對的。但是從面向對象程序員的分類來說,我又不完全懂得面向對象的思想。從事面向對象編程的人按照分工來說,可以分為“類庫的創建者”和“類庫的使用者”,通常創建類庫的人才是真正懂得面向對象思想的人,他們創建類庫供給那些“客戶程序員”來使用,他們從頭開始制作類庫,他們進行面向對象的分析,設計,實現的全過程。當學習完 C++ 後,我的第一個感覺是,從頭創建一個類庫真是很麻煩的事情,通常用 C 過程編程很輕易實現的功能,你必須按照類的思想來從新建立對象,但是一旦類庫建立好後,使用類庫和派生類,以及維護代碼都是非常舒適的事情。使用類庫的人並不都是具備了面向對象思想的人,通常知道如何繼續和派生新對象就可以使用類庫了,然而我們的思維並沒有真正的轉過來,使用類庫只是在形式上是面向對象,而實質上只是庫函數的一種擴展。這就是我理解的“C++ 是打著面向對象的幌子,干著過程編程的勾當”的第二重意思,實際上用 C++ 編程的人,大部分不自己創建類,而是使用類庫,這樣就造成了他們把類庫作為一種高級的庫函數庫來理解,並沒有真正理解面向對象的思想。
C++ 的面向對象的思想推廣很慢,直到 MFC ,OWL ,VCL 這樣的類庫出來以後,人們才漸漸的接受了一些面向對象的思想。為什麼這條面向對象的道路那麼難走?我的答案是“因為 C++ 給了我們第二條道路去走過程編程”,當然原因是為了考慮兼容 C 語言,然而正是由於有了第二條老路才使得使得我們不會再去考慮新的面向對象編程思維方式。