開篇之前先說明一下,我和老莊有著不錯的私交,他最初寫喪鐘系列的時候,我是忠實的擁躉之一,莊兄見我尚有寸尺所長,還在喪鐘系列里引用了我的幾個觀點。然而最近一段時間里,我作了這樣幾件事情:





經過種種之后,發現當初所謂鳴OO之喪鐘,實在是言過其實。
--------------------------------------------------------------------------------------------------------------------------------------------------------------
第0 關于"面向對象"
既然要為人家敲喪鐘,先要找對了苦主,不然豈不是白忙活了一場。什么是面向對象?這個問題太大,我們舉一個很常見的例子:



























































這個例子自然很不充分,不過繼承啊,接口啊,多態啊,略舉大概,尚可以作為一個討論的例子。從這個例子里,我們發現有這樣一個事實,就是Person類有兩個方法


分別表示,需要一個類型為Instrument的對象instrument,然后對他進行相應的操作,而且,從概念上來講,第一個方法,使演奏旋律的,也就是單音,而第二個方法是演奏和聲的。那么,如果我有一個類











我們知道,玻璃瓶裝了水也是可以發出聲音,Mozart可是為玻璃瓶寫過曲子的,而這里我們卻不能



因為我們在構造Person類的時候,我們的play方法是依賴一個類型為Instrument的Object,換而言之,我們這里所謂的Object-Oriented其實稱作Object-with-Type-Oriented的更合適,其實這類語言有一個專有名詞,叫做static type object oriented。那Object-Oriented是不是就一定是Static Type Object Oriented的呢?不然,比如在Ruby里,我們可以寫成:


























然后就可以



同樣也可以

在這里,類型可以推演也可以留到runtime檢查,如果是推演的話,在playNote里,由于thing調用了playNote方法,所以傳進來的對象必須要刻意接受playNote這個消息,于是Guitar和GlassBottle都是可以通過,因此我即可以演奏我的Perez 711,也可以敲玻璃瓶。這種方式叫做dynamic type。
那么static type和dynamic type區別在那呢?static type認為,class就是type,type就是class; subclass就是subtyping,subtyping就是subclass(其實這句不嚴謹,在c++里可以使得subclass不是subtyping,但是java里就沒辦法了);而dynamic type則認為類型和class沒有關系,類型取決于一個對象能夠接受的消息。
那么哪個才是面向對象之真貌呢?遺憾的說,static type并不是最初的面向對象。以對象作為模塊化的單位,始自Simula 67。但是Simula 67并不是一個面向對象系統,以目前的觀點來看,充其量是Object-based,第一個面向對象語言當推Smalltalk,Smalltalk是dynamic type的。不過Smalltalk不太流行,第一個大面積流行的面向對象語言是C++,C++是static type的,正如Lisp是第一個函數式編程語言,很多Lisp的特性被當作函數式語言的共有特性(比如表是最重要的數據結構,輕語法)一樣,所以很多人以為面向對象就必然是static type(比如老莊和我)。對于面向對象的誤解,80%來自C++。也就是說,80%來自于static type的面向對象系統。將static type面向對象歸咎于整個面向對象,我輩實在是大而無當言過其實。
后面我再一一將老莊所言之OO不當之處加以說明
所以,將我的文章,改為《敲響靜態類型OO時代的喪鐘》,應該是更為恰當的。
剛才跟徐X在MSN上聊,他已經基本上答應寫一個《YAST - Yet Another Smalltalk Tutorial》了。大家都有福了!
哈哈!
我也隨便說兩句,捧捧場,不當之處還請各位高人批評啊。 :)
個人覺得《Thinking In Java》的開篇:Everything is an Object影響了不少人的思維,至少我當年也把Java當作是最為純正的OO語言,因為最簡單的Hello,World都必須用上class這樣的高級的關鍵字。然而現在看起來,Java所強調的并不是Object,而是Everything is a Type。
在OO當中,Type已經被抬得太高了,以致影響了思維。其實像Python那樣,不把
Class當作first class(將function的地位提高至與Class一致)的時候,當繼承只是為了減少代碼復制的時候,很多事情都會變得很簡單。
還是很喜歡Python的靈活,少掉了很多束縛,卻不失嚴謹~~
http://www.jot.fm/issues/issue_2003_05/column2
在JVM spec一書中,作者強調:運行時沒有Type只有Class,所以java對Type與Class是有區別的。
在Inside JVM一書中,有言:不采用全反射目的是為了維運行 時護類型(Class)系統的穩定性。