計算機二級C++輔導:面向?qū)ο笳Z言概論(一)

字號:

本書是我們上面向?qū)ο箢愋屠碚摰慕滩?。當時上這門課時,心里滿不以為然,覺得自己的C++和OO已經(jīng)頗有造紙,C++和Java的類型系統(tǒng)不說倒背如流,也是輕車熟路,上這么一門課不是白拿學分?哈哈!
    但一上起來,才發(fā)現(xiàn)自己竟如井底之蛙一樣。老天,原來就這么簡單的面向?qū)ο缶褂羞@么多說道!原來除了C++, Java, 面向?qū)ο筮€有這么多沒見過甚至沒想過的東西!
    前幾章概論,勉強還都搞定了。但后面上到類型系統(tǒng)的建模,subject reduction的證明,就發(fā)現(xiàn)自己就象回到了本科時代,這,這,這怎么都是數(shù)學?。?BR>    這兩天心血來潮。就想把它翻譯一下。后面艱深的地方自覺功力太淺,就不不自量力了。不過,倒可以把前面幾章的概論翻譯一下,如果能起到幫助大家開闊眼界的作用,也就沒白費勁。
    第二章,基于類的面向?qū)ο笳Z言
    基于類的面向?qū)ο笳Z言是面向?qū)ο笫澜缋锏闹髁鳌Kǎ?BR>    Simula, 第一個面向?qū)ο笳Z言
    Smalltalk, 第一個支持動態(tài)類型的語言
    C++, 它的大部分基于類的特性繼承自Simula.與基于類的語言相對應的是基于對象的面向?qū)ο笳Z言。這里“基于對象”的概念和把Visual Basic叫做基于對象的概念是不同的。這里的“基于對象”是指一個只以對象為中心,沒有類的概念的語言,類似Python之類的語言。
    現(xiàn)在,我們來介紹一下基于類的面向?qū)ο笳Z言的一些共同特征。
    1.類和對象
    讓我們先看一個類的定義:
    class cell is
    var contents: Integer :=0;
    method get(): Integer is
    return self.contents;
    end;
    method set(n:Integer) is
    self.contents := n;
    end;
    end;
    一個類是用來描述所有屬于這個類的對象的共同結(jié)構(gòu)的。這個cell類表示的對象擁有一個叫做contents的整數(shù)屬性(attribute),這個屬性被初始化成0。它還描述了兩個操作contents的方法。Get和set. 這兩個方法的內(nèi)容都是很直觀的。Self變量表示這個對象自己。
    對象的動態(tài)語義可以這樣理解:
    一個對象在內(nèi)部被表示為一個指向一組屬性的指針。任何對這個對象的操作都會經(jīng)過這個指針操作對象的屬性和方法。而當對象被賦值或被當作參數(shù)傳遞的時候,所傳遞的只是指針,這樣一來,同一組屬性就可以被共享。
    (注, 有些語言如C++, 明確區(qū)分指向?qū)傩越M的指針和屬性組本身,而一些其它的語言則隱藏了這種區(qū)別)
    對象可以用new從一個類中實例化。準確地說,new C分配了一組屬性,并返回指向這組屬性的指針。這組屬性被賦予了初始值,并包括了類C所定義的方法的代碼。
    下面我們來考慮類型。對一個new C所生成的對象,我們把它的類型記為InstanceTypeOf(c). 一個例子是:
    var myCell: InstanceTypeOf(cell) := new cell;
    這里,通過引入InstanceTypeOf(cell), 我們開始把class和type區(qū)分開來了。我們也可以把cell本身當作是類型,但接下來,你就會發(fā)現(xiàn),那樣做會導致混淆的。
    2.方法解析。(Method Lookup)
    給出一個方法的調(diào)用o.m(……), 一個由各個語言自己實現(xiàn)的叫做方法解析的過程負責找到正確的方法的代碼。(譯者按:是不是想起了vtable了?)。
    直觀地看,方法的代碼可以被嵌入各個單個對象中,而且,對于許多面向?qū)ο笳Z言,對屬性和方法的相似的語法,也確實給人這種印象。
    不過,考慮到節(jié)省空間,很少有語言這樣實現(xiàn)。比較普遍的方法是,語言會生成許多method suite, 而這些method suite可以被同一個類的對象們所共享。方法解析過程會延著對象內(nèi)指向method suite的指針找到方法。
    在考慮到繼承的情況,方法解析會更加復雜化。Method suite也許會被組成一個樹,而對一個方法的解析也許要查找一系列method suite. 而如果有多繼承的話,method suite甚至可能組成有向圖,或者是環(huán)。
    方法解析可能發(fā)生在編譯時,也可能發(fā)生在運行時。
    在一些語言中,方法到底是嵌入對象中的,還是存在于method suite中這種細節(jié),對程序員是無關(guān)緊要的。因為,所有能區(qū)分這兩種模式的語言特性一般在基于類的面向?qū)ο笳Z言中都不被支持。
    比如說,方法并不能象屬性一樣從對象中取出來當作函數(shù)使用。方法也不能象屬性一樣在對象中被更新。(也就是說,你更新了一個對象的方法,而同一個類的其它對象的該方法保持不變。)
    3. 子類和繼承 (Subclassing and Inheritance)
    子類和一般的類一樣,也是用來描述對象的結(jié)構(gòu)的。但是,它是通過繼承其它類的結(jié)構(gòu)來漸進式地實現(xiàn)這個目的。
    父類的屬性會被隱式地復制到子類,子類也可以添加新的屬性。在一些語言中,子類甚至可以override父類的屬性(通過更改屬性的類型來實現(xiàn))
    父類中的方法可以被復制到子類,也可以被子類override.
    一個子類的代碼的示例如下:
    subclass reCell of cell is
    var backup: Integer := 0;
    override set(n: Integer) is
    self.backup := self.contents;
    super.set(n);
    end;
    method restore() is
    self.contents := self.backup;
    end;
    end;
    對有subclass的方法解析,根據(jù)語言是靜態(tài)類型還是動態(tài)類型而有所不同。
    在靜態(tài)類型的語言(如C++, Java)里,父類,子類的method suite的拓撲結(jié)構(gòu)在編譯時就已經(jīng)確定,所以可以把父類的method suite里的方法合并到子類的method suite中去,方法解析時就不用再搜索這個method suite的樹或圖了。(譯者按:C++的vtable就是這種方法)而對于動態(tài)類型的語言,(也就是說,父子類的關(guān)系是在運行時決定的),method suite就無法合并了。所以,方法解析時,就要沿著這個動態(tài)生成的樹或有向圖搜索直到找到合適的方法。而如果語言支持多繼承,這個搜索就更復雜了。