09丨面向?qū)ο髮?shí)現(xiàn)數(shù)據(jù)和方法的封裝_W_第1頁(yè)
09丨面向?qū)ο髮?shí)現(xiàn)數(shù)據(jù)和方法的封裝_W_第2頁(yè)
09丨面向?qū)ο髮?shí)現(xiàn)數(shù)據(jù)和方法的封裝_W_第3頁(yè)
09丨面向?qū)ο髮?shí)現(xiàn)數(shù)據(jù)和方法的封裝_W_第4頁(yè)
09丨面向?qū)ο髮?shí)現(xiàn)數(shù)據(jù)和方法的封裝_W_第5頁(yè)
已閱讀5頁(yè),還剩8頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、 下載APP 09 | 面向?qū)ο螅簩?shí)現(xiàn)數(shù)據(jù)和方法的封裝2019-09-02 宮文學(xué)編譯原理之美進(jìn)入課程 講述:宮文學(xué)時(shí)長(zhǎng) 13:34 大小 9.33M在現(xiàn)代計(jì)算機(jī)語(yǔ)言中,面向?qū)ο笫欠浅V匾奶匦?,似乎常用的語(yǔ)言都支持面向?qū)ο筇匦裕?比如 Swift、C+、Java不支持的反倒是異類(lèi)了。而它重要的特點(diǎn)就是封裝。也就是說(shuō),對(duì)象可以把數(shù)據(jù)和對(duì)數(shù)據(jù)的操作封裝在一起,構(gòu)成一個(gè)不可分割的整體,盡可能地隱藏內(nèi)部的細(xì)節(jié),只保留一些接口與外部發(fā)生聯(lián)系。 在對(duì)象的外部只能通過(guò)這些接口與對(duì)象進(jìn)行交互,無(wú)需知道對(duì)象內(nèi)部的細(xì)節(jié)。這樣能降低系統(tǒng)的耦合, 實(shí)現(xiàn)內(nèi)部機(jī)制的隱藏,不用擔(dān)心對(duì)外界的影響。那么它們是怎樣實(shí)現(xiàn)的呢?本

2、節(jié)課,我將從語(yǔ)義設(shè)計(jì)和運(yùn)行時(shí)機(jī)制的角度剖析面向?qū)ο蟮奶匦裕瑤闵钊肜斫饷嫦驅(qū)ο?的實(shí)現(xiàn)機(jī)制,讓你能在日常編程工作中更好地運(yùn)用面向?qū)ο蟮奶匦?。比如,在學(xué)完這講之后,你會(huì)對(duì)對(duì)象的作用域和生存期、對(duì)象初始化過(guò)程等有更清晰的了解。而且你不會(huì)因?yàn)閷W(xué)習(xí)了 Java 或 C+ 的面向?qū)ο髾C(jī)制,在學(xué)習(xí) JavaScript 和 Ruby 的面向?qū)ο髾C(jī)制時(shí)覺(jué)得別扭,因?yàn)樗鼈兊谋举|(zhì)是一樣的。接下來(lái),我們先簡(jiǎn)單地聊一下什么是面向?qū)ο?。面向?qū)ο蟮恼Z(yǔ)義特征我的一個(gè)朋友,在 10 多年前做過(guò)培訓(xùn)師,為了吸引學(xué)員的注意力,他在講“什么是面向?qū)ο蟆睍r(shí)說(shuō):“面向?qū)ο笫鞘澜缬^,是方法論?!彪m然有點(diǎn)兒語(yǔ)不驚人死不休的意思,但我必須

3、承認(rèn),所有的計(jì)算機(jī)語(yǔ)言都是對(duì)世界進(jìn)行建模的方式,只不過(guò)建模的視角不同罷了。面向?qū)ο蟮脑O(shè)計(jì)思想,在上世紀(jì) 90 年代被推崇,幾乎被視為最好的編程模式。實(shí)際上,各種不同的編程思想,都會(huì)表現(xiàn)為這門(mén)語(yǔ)言的語(yǔ)義特征, 所以,我就從語(yǔ)義角度,利用類(lèi)型、作用域、生存期這樣的概念帶你深入剖析一下面向?qū)ο蟮姆庋b特性,其他特性在后面的課程中再去討論。從類(lèi)型角度類(lèi)型處理是語(yǔ)義分析時(shí)的重要工作?,F(xiàn)代計(jì)算機(jī)語(yǔ)言可以用自定義的類(lèi)來(lái)聲明變量,這是一個(gè)巨大的進(jìn)步。因?yàn)樵缙诘挠?jì)算機(jī)語(yǔ)言只支持一些基礎(chǔ)的數(shù)據(jù)類(lèi)型,比如各種長(zhǎng)短不一的整型和浮點(diǎn)型,像字符串這種我們編程時(shí)離不開(kāi)的類(lèi)型,往往是在基礎(chǔ)數(shù)據(jù)類(lèi)型上封裝和抽象出來(lái)的。所以,我們

4、要擴(kuò)展語(yǔ)言的類(lèi)型機(jī)制,讓程序員可以創(chuàng)建自己的類(lèi)型。從作用域角度首先是類(lèi)的可見(jiàn)性。作為一種類(lèi)型,它通常在整個(gè)程序的范圍內(nèi)都是可見(jiàn)的,可以用它聲明變量。當(dāng)然,一些像 Java 的語(yǔ)言,也能限制某些類(lèi)型的使用范圍,比如只能在某個(gè)命名空間內(nèi),或者在某個(gè)類(lèi)內(nèi)部。對(duì)象的成員的作用域是怎樣的呢?我們知道,對(duì)象的屬性(“屬性”這里指的是類(lèi)的成員變量)可以在整個(gè)對(duì)象內(nèi)部訪問(wèn),無(wú)論在哪個(gè)位置聲明。也就是說(shuō),對(duì)象屬性的作用域是整個(gè)對(duì)象的內(nèi)部,方法也是一樣。這跟函數(shù)和塊中的本地變量不一樣,它們對(duì)聲明順序有要求, 像 C 和 Java 這樣的語(yǔ)言,在使用變量之前必須聲明它。從生存期的角度對(duì)象的成員變量的生存期,一般跟對(duì)

5、象的生存期是一樣的。在創(chuàng)建對(duì)象的時(shí)候,就對(duì)所有成員變量做初始化,在銷(xiāo)毀對(duì)象的時(shí)候,所有成員變量也隨著一起銷(xiāo)毀。當(dāng)然,如果某個(gè)成員引用了從堆中申請(qǐng)的內(nèi)存,這些內(nèi)存需要手動(dòng)釋放,或者由垃圾收集機(jī)制釋放。但還有一些成員,不是與對(duì)象綁定的,而是與類(lèi)型綁定的,比如 Java 中的靜態(tài)成員。靜態(tài)成員跟普通成員的區(qū)別,就是作用域和生存期不同,它的作用域是類(lèi)型的所有對(duì)象實(shí)例,被所有實(shí)例共享。生存期是在任何一個(gè)對(duì)象實(shí)例創(chuàng)建之前就存在,在最后一個(gè)對(duì)象銷(xiāo)毀之前不會(huì)消失。你看,我們用這三個(gè)語(yǔ)義概念,就把面向?qū)ο蟮姆庋b特性解釋清楚了,無(wú)論語(yǔ)言在頂層怎么設(shè)計(jì),在底層都是這么實(shí)現(xiàn)的。了解了面向?qū)ο笤谡Z(yǔ)義上的原理之后,我們來(lái)

6、實(shí)際動(dòng)手解析一下代碼中的類(lèi),這樣能更深刻地體會(huì)這些原理。設(shè)計(jì)類(lèi)的語(yǔ)法,并解析它我們要在語(yǔ)言中支持類(lèi)的定義,在 PlayScript.g4 中,可以這樣定義類(lèi)的語(yǔ)法規(guī)則: 復(fù)制代碼 1 classDeclaration2:CLASS IDENTIFIER3(EXTENDS typeType)?4(IMPLEMENTS typeList)?5classBody6;78classBody9: classBodyDeclaration*10;1112classBodyDeclaration13: ;14| memberDeclaration15;1617memberDeclaration18: fun

7、ctionDeclaration19| fieldDeclaration20;2122functionDeclaration23: typeTypeOrVoid IDENTIFIERformalParameters ( )*242526;(THROWS qualifiedNameList)? functionBody我來(lái)簡(jiǎn)單地講一下這個(gè)語(yǔ)法規(guī)則:類(lèi)聲明以 class 關(guān)鍵字開(kāi)頭,有一個(gè)標(biāo)識(shí)符是類(lèi)型名稱(chēng),后面跟著類(lèi)的主體。類(lèi)的主體里要聲明類(lèi)的成員。在簡(jiǎn)化的情況下,可以只關(guān)注類(lèi)的屬性和方法兩種成員。我們故意把類(lèi)的方法也叫做 function,而不是 method,是想把對(duì)象方法和函數(shù)做一些統(tǒng)一的設(shè)

8、計(jì)。函數(shù)聲明現(xiàn)在的角色是類(lèi)的方法。類(lèi)的成員變量的聲明和普通變量聲明在語(yǔ)法上沒(méi)什么區(qū)別。你能看到,我們構(gòu)造像 class 這樣高級(jí)別的結(jié)構(gòu)時(shí),越來(lái)越得心應(yīng)手了,之前形成的一些基礎(chǔ)的語(yǔ)法模塊都可以復(fù)用,比如變量聲 碼塊(block)等。用上面的語(yǔ)法寫(xiě)出來(lái)的 playscript 腳本的效果如下,在示例代碼里也有,你可以運(yùn)行它: 復(fù)制代碼 1 /*2 ClassTest.play 簡(jiǎn)單的面向?qū)ο筇匦浴?3 */4 class Mammal5 / 類(lèi)屬性 6 string name = ;78 / 構(gòu)造方法 9 Mammal(string str)10 name = str;111213/ 方法 14

9、 void speak()15 println(mammal + name + speaking.);1617 1819 Mammal mammal = Mammal(dog); /playscript 特別的構(gòu)造方法,不需要 new 關(guān)鍵字 20 mammal.speak();/ 訪問(wèn)對(duì)象方法 21 println( = + ); / 訪問(wèn)對(duì)象的屬性 2223 / 沒(méi)有構(gòu)造方法,創(chuàng)建的時(shí)候用缺省構(gòu)造方法 24 class Bird25 int speed = 50;/ 在缺省構(gòu)造方法里初始化 2627 void fly()28 println(bi

10、rd flying.);2930 3132 Bird bird = Bird();/ 采用缺省構(gòu)造方法 33 println(bird.speed : + bird.speed + km/h);34 bird.fly();接下來(lái),我們讓 playscript 解釋器處理這些看上去非?,F(xiàn)代化的代碼,怎么處理呢?做完詞法分析和語(yǔ)法分析之后,playscript 會(huì)在語(yǔ)義分析階段掃描 AST,識(shí)別出所有自定義的類(lèi)型,以便在其他地方引用這些類(lèi)型來(lái)聲明變量。因?yàn)轭?lèi)型的聲明可以在代碼中的任何位置,所以最好用單獨(dú)的一次遍歷來(lái)識(shí)別和記錄類(lèi)型(類(lèi)型掃描的代碼在TypeAndScopeScanner.java 里

11、)。接著,我們?cè)诼暶髯兞繒r(shí),就可以引用這個(gè)類(lèi)型了。語(yǔ)義分析的另一個(gè)工作,就是做變量類(lèi)型的消解。當(dāng)我們聲明“Bird bird = Bird(); ”時(shí),需要知道 Bird 對(duì)象的定義在哪里,以便正確地訪問(wèn)它的成員(變量類(lèi)型的消解在 TypeResolver.java 里)。在做語(yǔ)義分析時(shí),要把類(lèi)型的定義保存在一個(gè)數(shù)據(jù)結(jié)構(gòu)中,我們來(lái)實(shí)現(xiàn)一下: 復(fù)制代碼 1 public class Class extends Scope implements Type2.3 45 public abstract class Scope extends Symbol6 / 該 Scope 中的成員,包括變量、方法

12、、類(lèi)等。 7 protected List symbols = new LinkedList(8 910 public interface Type 11 public String getName();/ 類(lèi)型名稱(chēng) 1213public Scope getEnclosingScope();14 在這個(gè)設(shè)計(jì)中,我們看到 Class 就是一個(gè) Scope,Scope 里面原來(lái)就能保存各種成員,現(xiàn)在可以直接復(fù)用,用來(lái)保存類(lèi)的屬性和方法,畫(huà)成類(lèi)圖如下:圖里有幾個(gè)類(lèi),比如 Symbol、Variable、Scope、Function 和 BlockScope,它們是我們的符號(hào)體系的主要成員。在做詞法分

13、析時(shí),我們會(huì)解析出很多標(biāo)識(shí)符,這些標(biāo)識(shí)符出現(xiàn)在不同的語(yǔ)法規(guī)則里,包括變量聲明、表達(dá)式,以及作為類(lèi)名、方法名等出現(xiàn)。在語(yǔ)義分析階段,我們要把這些標(biāo)識(shí)符一一識(shí)別出來(lái),這個(gè)是一個(gè)變量,指的是一個(gè)本地變量;那個(gè)是一個(gè)方法名等。變量、類(lèi)和函數(shù)的名稱(chēng),我們都叫做符號(hào),比如示例程序中的Mammal、Bird、mammal、bird、name、speed 等。編譯過(guò)程中的一項(xiàng)重要工作就是建立符號(hào)表,它幫助我們進(jìn)一步地編譯或執(zhí)行程序,而符號(hào)表就用上面幾個(gè)類(lèi)來(lái)保存信息。在符號(hào)表里,我們保存它的名稱(chēng)、類(lèi)型、作用域等信息。對(duì)于類(lèi)和函數(shù),我們也有相應(yīng)的地方來(lái)保存類(lèi)變量、方法、參數(shù)、返回值等信息。你可以看一看示例代碼里面

14、是如何解析和記錄這些符號(hào)的。解析完這些語(yǔ)義信息以后,我們來(lái)看運(yùn)行期如何執(zhí)行具有面向?qū)ο筇卣鞯某绦颍热缛绾螌?shí)例化一個(gè)對(duì)象?如何在內(nèi)存里管理對(duì)象的數(shù)據(jù)?以及如何訪問(wèn)對(duì)象的屬性和方法?對(duì)象是怎么實(shí)例化的首先通過(guò)構(gòu)造方法來(lái)創(chuàng)建對(duì)象。在語(yǔ)法中,我們沒(méi)有用 new 這個(gè)關(guān)鍵字來(lái)表示對(duì)象的創(chuàng)建,而是省略掉了 new,直接調(diào)用一個(gè)跟類(lèi)名稱(chēng)相同的函數(shù),這是我們獨(dú)特的設(shè)計(jì),示例代碼如下: 復(fù)制代碼 1 Mammal mammal = Mammal(dog); /playscript 特別的構(gòu)造方法,不需要 new 關(guān)鍵字 2 Bird bird = Bird();/ 采用缺省構(gòu)造方法 但在語(yǔ)義檢查的時(shí)候,在當(dāng)前

15、作用域中是肯定找不到這樣一個(gè)函數(shù)的,因?yàn)轭?lèi)的初始化方法是在類(lèi)的內(nèi)部定義的,我們只要檢查一下,Mammal 和 Bird 是不是一個(gè)類(lèi)名就可以了。再進(jìn)一步,Mammal 類(lèi)中確實(shí)有個(gè)構(gòu)造方法 Mammal(),而 Bird 類(lèi)中其實(shí)沒(méi)有一個(gè)顯式定義的構(gòu)造方法,但這并不意味著變量成員不會(huì)被初始化。我們借鑒了 Java 的初始化機(jī)制,就是提供缺省初始化方法,在缺省初始化方法里,會(huì)執(zhí)行對(duì)象成員聲明時(shí)所做的初始化工作。所以,上面的代碼里,我們調(diào)用 Bird(),實(shí)際上就是調(diào)用了這個(gè)缺省的初始化方法。無(wú)論有沒(méi)有顯式聲明的構(gòu)造方法,聲明對(duì)象的成員變量時(shí)的初始化部分,一定會(huì)執(zhí)行。對(duì)于Bird 類(lèi),實(shí)際上就會(huì)執(zhí)

16、行“int speed = 50;”這個(gè)語(yǔ)句。在 RefResolver.java 中做語(yǔ)義分析的時(shí)候,下面的代碼能夠檢測(cè)出某個(gè)函數(shù)調(diào)用其實(shí)是類(lèi)的構(gòu)造方法,或者是缺省構(gòu)造方法: 復(fù)制代碼 1 / 看看是不是類(lèi)的構(gòu)建函數(shù),用相同的名稱(chēng)查找一個(gè) class2 Class theClass = at.lookupClass(scope, idName);3 if (theClass != null) 4 function = theClass.findConstructor(paramTypes);5 if (function != null) 6 at.symbolOfNode.put(ctx,

17、function);78 / 如果是與類(lèi)名相同的方法,并且沒(méi)有參數(shù),那么就是缺省構(gòu)造方法 9 else if (ctx.expressionList() = null)10 at.symbolOfNode.put(ctx, theClass); / TODO 直接賦予 class1112 else13 at.log(unknown class constructor: + ctx.getText(), ctx);141516at.typeOfNode.put(ctx, theClass); / 這次函數(shù)調(diào)用是返回一個(gè)對(duì)象 17 當(dāng)然,類(lèi)的構(gòu)造方法跟普通函數(shù)還是有所不同的,例如我們不允許構(gòu)造方法

18、定義返回值,因?yàn)樗姆祷刂狄欢ㄊ沁@個(gè)類(lèi)的一個(gè)實(shí)例對(duì)象。對(duì)象做了缺省初始化以后,再去調(diào)用顯式定義的構(gòu)造方法,這樣才能完善整個(gè)對(duì)象實(shí)例化的過(guò)程。不過(guò)問(wèn)題來(lái)了,我們可以把普通的本地變量的數(shù)據(jù)保存在棧里,那么如何保存對(duì)象的數(shù)據(jù)呢?如何在內(nèi)存里管理對(duì)象的數(shù)據(jù)其實(shí),我們也可以把對(duì)象的數(shù)據(jù)像其他數(shù)據(jù)一樣,保存在棧里。C 語(yǔ)言的結(jié)構(gòu)體 struct 和 C+ 語(yǔ)言的對(duì)象,都可以保存在棧里。保存在棧里的對(duì)象是直接聲明并實(shí)例化的,而不是用 new 關(guān)鍵字來(lái)創(chuàng)建的。如果用 new 關(guān)鍵字來(lái)創(chuàng)建,實(shí)際上是在堆里申請(qǐng)了一塊內(nèi)存,并賦值給一個(gè)指針變量,如下圖所示:當(dāng)對(duì)象保存在堆里的時(shí)候,可以有多個(gè)變量都引用同一個(gè)對(duì)象,比

19、如圖中的變量 a 和變量b 就可以引用同一個(gè)對(duì)象 object1。類(lèi)的成員變量也可以引用別的對(duì)象,比如 object1 中的類(lèi)成員引用了 object2 對(duì)象。對(duì)象的生存期可以超越創(chuàng)建它的棧楨的生存期。我們可以對(duì)比一下這兩種方式的優(yōu)缺點(diǎn)。如果對(duì)象保存在棧里,那么它的生存期與作用域是一樣的,可以自動(dòng)的創(chuàng)建和銷(xiāo)毀,因此不需要額外的內(nèi)存管理。缺點(diǎn)是對(duì)象沒(méi)辦法長(zhǎng)期存在并共享。而在堆里創(chuàng)建的對(duì)象雖然可以被共享使用,卻增加了內(nèi)存管理的負(fù)擔(dān)。所以在 C 語(yǔ)言和 C+ 語(yǔ)言中,要小心管理從堆中申請(qǐng)的內(nèi)存,在合適的時(shí)候釋放掉這些內(nèi)存。在 Java 語(yǔ)言和其他一些語(yǔ)言中,采用的是垃圾收集機(jī)制,也就是說(shuō)當(dāng)一個(gè)對(duì)象不

20、再被引用時(shí),就把內(nèi)存收集回來(lái)。分析到這兒的時(shí)候,我們其實(shí)可以幫 Java 語(yǔ)言?xún)?yōu)化一下內(nèi)存管理。比如我們?cè)诜治龃a時(shí),如果發(fā)現(xiàn)某個(gè)對(duì)象的創(chuàng)建和使用都局限在某個(gè)塊作用域中,并沒(méi)有跟其他作用域共享, 那么這個(gè)對(duì)象的生存期與當(dāng)前棧楨是一致的,可以在棧里申請(qǐng)內(nèi)存,而不是在堆里。這樣可以免除后期的垃圾收集工作。分析完對(duì)象的內(nèi)存管理方式之后,回到 playscript 的實(shí)現(xiàn)。在 playscrip 的 Java 版本里, 我們用一個(gè) ClassObject 對(duì)象來(lái)保存對(duì)象數(shù)據(jù),而 ClassObject 是 PlayObject 的子類(lèi)。上一講,我們已經(jīng)講過(guò) PlayObject,它被棧楨用來(lái)保存本地變

21、量,可以通過(guò)傳入 Variable 來(lái)訪問(wèn)對(duì)象的屬性值: 復(fù)制代碼 1 / 類(lèi)的實(shí)例 2 public class ClassObject extends PlayObject3/ 類(lèi)型 4protected Class type = null;5.6 78 / 保存對(duì)象數(shù)據(jù) 9 public class PlayObject 10 / 成員變量 11 protected Map fields = new HashMap();1213public Object getValue(Variable variable)14Object rtn = fields.get(variable);15re

22、turn rtn;161718public void setValue(Variable variable, Object value)19fields.put(variable, value);2021在運(yùn)行期,當(dāng)需要訪問(wèn)一個(gè)對(duì)象時(shí),我們也會(huì)用 ClassObject 來(lái)做一個(gè)棧楨,這樣就可以像訪問(wèn)本地變量一樣訪問(wèn)對(duì)象的屬性了。而不需要訪問(wèn)這個(gè)對(duì)象的時(shí)候,就把它從棧中移除,如果沒(méi)有其他對(duì)象引用這個(gè)對(duì)象,那么它會(huì)被 Java 的垃圾收集機(jī)制回收。訪問(wèn)對(duì)象的屬性和方法在示例代碼中,我們用點(diǎn)操作符來(lái)訪問(wèn)對(duì)象的屬性和方法,比如: 復(fù)制代碼 1 mammal.speak();/ 訪問(wèn)對(duì)象方法 2 pr

23、intln( = + ); / 訪問(wèn)對(duì)象的屬性 屬性和方法的引用也是一種表達(dá)式,語(yǔ)法定義如下: 復(fù)制代碼 1 expression2: .3 | expression bop=.4 ( IDENTIFIER/ 對(duì)象屬性5 | functionCall/ 對(duì)象方法6)7.8;注意,點(diǎn)符號(hào)的操作可以是級(jí)聯(lián)的,比如: 復(fù)制代碼 1 obj1.obj2.field1;2 obj1.getObject2().field1;所以,對(duì)表達(dá)式的求值,要能夠獲得正確的對(duì)象引用,你可以運(yùn)行一下 ClassTest.play 腳本,或者去看看我的參考實(shí)現(xiàn)。另外,對(duì)象成員還

24、可以設(shè)置可見(jiàn)性。也就是說(shuō),有些成員只有對(duì)象內(nèi)部才能用,有些可以由外部訪問(wèn)。這個(gè)怎么實(shí)現(xiàn)呢?這只是個(gè)語(yǔ)義問(wèn)題,是在編譯階段做語(yǔ)義檢查的時(shí)候,不允許私有的成員被外部訪問(wèn),報(bào)編譯錯(cuò)誤就可以了,在其他方面,并沒(méi)有什么不同。課程小結(jié)我們針對(duì)面向?qū)ο蟮姆庋b特性,從類(lèi)型、作用域和生存期的角度進(jìn)行了重新解讀,這樣能夠更好地把握面向?qū)ο蟮谋举|(zhì)特征。我們還設(shè)計(jì)了與面向?qū)ο蟮南嚓P(guān)的語(yǔ)法并做了解析,然后討論了面向?qū)ο蟪绦虻倪\(yùn)行期機(jī)制,例如如何實(shí)例化一個(gè)對(duì)象,如何在內(nèi)存里管理對(duì)象的數(shù)據(jù),以及如何訪問(wèn)對(duì)象的屬性和方法。通過(guò)對(duì)類(lèi)的語(yǔ)法和語(yǔ)義的剖析和運(yùn)行機(jī)制的落地,我相信你會(huì)對(duì)面向?qū)ο蟮臋C(jī)制有更加本質(zhì)的認(rèn)識(shí),也能更好地使用語(yǔ)言的面向?qū)ο筇匦粤恕R徽n一思我們用比較熟悉的語(yǔ)法

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論