ruby語法基礎(chǔ)教程_第1頁
ruby語法基礎(chǔ)教程_第2頁
ruby語法基礎(chǔ)教程_第3頁
ruby語法基礎(chǔ)教程_第4頁
ruby語法基礎(chǔ)教程_第5頁
已閱讀5頁,還剩83頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、Grant Renhyqryq2006年11月24日 前 言 目 錄Ruby語言1Grant Ren1第一部分 Ruby語言基礎(chǔ)8第一章 Ruby語言概述8§1.1 Ruby的歷史8§1.2 Ruby名字的由來8§1.3 Ruby的特點(diǎn)8§1.4 Ruby和Python的比較9第二章 Ruby編程環(huán)境9§2.1 Ruby的安裝9§2.1.1 在Windows 95/98/Me/XP上安裝Ruby9§2.1.2 在Linux上安裝Ruby10§2.2 運(yùn)行Ruby10§2.2.1 使用Ruby10§

2、;2.2.2 使用FreeRIDE和SciTE11§2.2.3 使用fxri13§2.3 Ruby-irb14§2.4 Ruby-ri15§2.5 RubyGems15第三章類與對(duì)象17§3.1 類的定義17§3.2 對(duì)象,屬性和方法18§3.3 繼承20§3.4 特殊方法與特殊類21§3.5 類變量與類方法23§3.4 存取控制23§3.6 元類25§3.7 Ruby的動(dòng)態(tài)性26§3.8 變量26§3.8.1 局部變量27§3.8.2 實(shí)例變量

3、27§3.8.3 類變量27§3.8.4 全局變量28§3.8.5 常量28§3.8 與定義有關(guān)的操作29§3.8.1 alias29§3.8.2 undef30§3.8.3 defined?31第四章基本類型33§4.1 Array33§4.2 Hash34§4.3 Number34§4.4 String35§4.5 Range36§4.6 Symbol37§4.7 正則表達(dá)式37第五章代碼塊和迭代器38§5.1 代碼塊(Block)38

4、67;5.1.1 什么是代碼塊38§5.1.2 代碼塊與對(duì)象39§5.2 迭代器(Iterator)40§5.2.1 什么是迭代器40§5.2.2 使用迭代器40§5.2.3 yield41§5.2.4 編寫自己的迭代器42第六章表達(dá)式42§6.1 運(yùn)算符43§6.2 命令替換44§6.3 賦值運(yùn)算符44§6.4 并行賦值46§6.5 嵌套賦值47§6.6 其他賦值47§6.7 條件運(yùn)算47§6.8 case表達(dá)式48§6.9 循環(huán)49§

5、;6.9.1 Loop49§6.9.2 While50§6.9.3 Until50§6.9.4 Iterator50§6.9.5 For.In51§6.9.6 Break,Redo,Next51§6.9.7 Retry53第七章方法54§7.1 運(yùn)算符重定義55§7.2 變長參數(shù)56§7.3 塊調(diào)用56§7.4 方法返回值57第八章模塊59§8.1 名字空間59§8.2 mixin59§8.3 使用mixin60§8.3.1 Comparable60

6、67;8.3.2 Enumerable61§8.3.3 Singleton62§8.4 Require, load和include62第九章異常64§9.1 異常處理64§9.2 定義異常類68§9.3 catch和throw68第十章多任務(wù)處理69§10.1 多線程處理69§10.1.1 線程創(chuàng)建69§10.1.2 線程操作70§10.1.3 線程和異常71§10.1.4 線程調(diào)度73§10.1.5 線程同步73§10.2 多進(jìn)程處理79§10.2.1 進(jìn)程創(chuàng)建7

7、9第十一章基本I/O操作80§11.1 使用Kernel模塊處理I/O操作80§11.2文件處理80§11.3 StringIO81§11.4 Socket82第十二章反射和對(duì)象空間82§12.1 ObjectSpace模塊82§12.2 察看類和對(duì)象的狀態(tài)83§12.3 動(dòng)態(tài)方法調(diào)用86§12.3.1 使用send方法86§12.3.2 使用Method類和UnboundMethod類86§12.3.3 使用eval方法88§12.3.4 性能88§12.4 Hook和回調(diào)

8、方法89§12.4.1 什么是Hook89§12.4.2 Ruby中的Hook89§11.4.2 回調(diào)方法90§12.5 跟蹤程序的運(yùn)行90§12.5.1 set_trace_func90§12.5.2 trace_var91§12.5.3 caller91§12.5.3 _FILE_,_LINE_和SCRIPT_LINES_92第十三章序列化和YAML92§13.1 序列化的概念92§13.2 使用序列化93§13.2.1 二進(jìn)制數(shù)據(jù)保存93§13.2.2 YAML數(shù)據(jù)保存

9、93§13.3 定制序列化94§13.3.1 二進(jìn)制數(shù)據(jù)保存94§13.3.2 YAML數(shù)據(jù)保存95§13.3 YAML95§13.3.1 集合類型96§13.3.2 單行集合類型99§13.3.3 基本類型99§13.3.4 塊99§13.3.5 別名和錨(Aliases and Anchors)99§13.3.6 文檔99§13.3.7 Ruby中YAML的使用99第十四章安全控制100§14.1 0級(jí)101§14.1 1級(jí)101§14.2 2級(jí)101

10、§14.3 3級(jí)101§14.4 4級(jí)101第十五章單元測試101§15.1 什么是單元測試101§15.2 Ruby單元測試框架101第二部分內(nèi)置類與模塊101第一章內(nèi)置類102§1.1 Array102§1.2 Bignum102§1.3 Binding102§1.4 Class102§1.5 Continuation102§1.6 Dir104§1.7 Exception104§1.8 FalseClass104§1.9 File104§1.10 F

11、ile:Stat104§1.11 Fixnum104§1.12 Float104§1.13 Hash104§1.14 Integer104§1.15 IO104§1.16 MatchData104§1.17 Method104§1.18 Module104§1.19 NilClass104§1.20 Numeric104§1.21 Object104§1.22 Proc105§1.23 Process:Status105§1.24 Range105

12、7;1.25 Regexp105§1.26 String105§1.27 Struct105§1.28 Struct:Tms105§1.29 Symbol105§1.30 Thread105§1.31 ThreadGroup105§1.32 Time105§1.33 TrueClass105§1.34 UnboundMethod105第二章內(nèi)置模塊106§2.1 Comparable106§2.2 Enumerable106§2.3 Error106§2.4 Fil

13、eTest106§2.5 GC106§2.6 Kernel106§2.7 Marshal106§2.8 Math106§2.9 ObjectSpace106§2.10 Process106§2.11 Process:GID106§2.12 Process:Sys106§2.13 Process:UID106§2.14 Signal106第三部分 Ruby語言總結(jié)107附錄110§1 術(shù)語對(duì)照110第一部分 Ruby語言基礎(chǔ)第一章 Ruby語言概述§1.1Ruby的歷史Ruby

14、語言的發(fā)明人是日本人松本行弘(Matsumoto Yukihiro),大家親切的稱呼他"Matz"??赡軙?huì)出乎大家的意料,Ruby并不是一種近年來才誕生的語言,它的歷史可以追溯到1993年,Ruby之父Matz開始對(duì)腳本語言感興趣。在通過一些分析和思考之后,Matz認(rèn)為腳本語言是可以變得很強(qiáng)大和靈活的,于是他準(zhǔn)備把腳本語言作為他的發(fā)展方向。 和很多人一樣,Matz是一個(gè)面向?qū)ο蟪绦蛟O(shè)計(jì)的fans,自然而然他想研究一種支持面向?qū)ο蟪绦蛟O(shè)計(jì)的腳本語言。隨后的一段時(shí)間,他到網(wǎng)絡(luò)上搜集了一些相關(guān)的資料,并且發(fā)現(xiàn)了Perl 5,當(dāng)時(shí)Perl 5還沒有發(fā)布。通過一段時(shí)間了解后,Matz

15、.發(fā)現(xiàn)Perl 5這并不是他想的東西,所以他放棄了把Perl當(dāng)作一個(gè)面向?qū)ο蟮哪_本語言使用的念頭。隨后Matz轉(zhuǎn)向了Python,Python是一個(gè)解釋型的、面向?qū)ο笳Z言,但是Matz發(fā)現(xiàn)Python并不能完全算作“面向?qū)ο蟆闭Z言。Matz認(rèn)為Python是面向?qū)ο蠛瓦^程化程序設(shè)計(jì)語言(Procedural Programming Language)的混合產(chǎn)物。Matz希望找到的是一種比Perl更強(qiáng)大、比Python更面向?qū)ο蟮恼Z言,但是很遺憾, 這樣的語言當(dāng)時(shí)在地球上并不存在。于是Matz打算自己設(shè)計(jì)一個(gè)全新的編程語言。1993年2月24日是一個(gè)值得紀(jì)念的日子,在這一天Ruby誕生了。 19

16、95年12月Matz推出了Ruby的第一個(gè)版本Ruby 0.95。 在1996年以前,都是Matz.一個(gè)人在開發(fā)進(jìn)行Ruby的開發(fā)。后來隨著Ruby社區(qū)的漸漸形成,很多社區(qū)成員給了Matz許多有意義的幫助,包括提交bug和patch等?,F(xiàn)在,Ruby像其他開源項(xiàng)目一樣,有自己的開發(fā)團(tuán)隊(duì),任何有能力的個(gè)人或團(tuán)體都可以參與Ruby的開發(fā)與進(jìn)化。§1.2 Ruby名字的由來首先明確一點(diǎn),Ruby并不是其他單詞的縮寫。受Perl的影響,Matz也想用一種寶石來命名他的新語言,他使用了他的一位同事的生肖石紅寶石。后來,Matz意識(shí)到Ruby這個(gè)名字十分恰當(dāng),首先,在生肖石中,Pearl代表六月

17、,而Ruby代表七月。在字體大小上,Pearl大小是5pt, ruby的大小是5.5pt。所以Ruby這個(gè)名字對(duì)于一種Perl的后續(xù)語言十分合適。§1.3 Ruby的特點(diǎn)Ruby是一種功能強(qiáng)大的面向?qū)ο蟮哪_本語言,可以使用它方便快捷地進(jìn)行面向?qū)ο蟪绦蛟O(shè)計(jì)。與Perl類似,而且Ruby具有強(qiáng)大的文本處理功能,使文本處理變得簡單。此外還可以方便地使用C語言來擴(kuò)展Ruby的功能。若您曾經(jīng)“想要一種簡單的面向?qū)ο蟮恼Z言”,或者認(rèn)為“Perl的功能雖然好用,但它的語法真讓人受不了”,又或者覺得“LISP系列語言的思想不錯(cuò),但到處都是括號(hào)真讓人討厭,最起碼算式應(yīng)該按照通常的樣式書寫”。那么,Ru

18、by或許能讓您滿意。歸納起來,Ruby有以下優(yōu)點(diǎn):l 解釋型執(zhí)行,方便快捷Ruby是解釋型語言,其程序無需編譯即可執(zhí)行。l 語法簡單、優(yōu)雅語法比較簡單,類似Algol系語法。l 完全面向?qū)ο驲uby從一開始就被設(shè)計(jì)成純粹的面向?qū)ο笳Z言,因此所有東西都是對(duì)象,例如整數(shù)等基本數(shù)據(jù)類型。l 內(nèi)置正則式引擎,適合文本處理Ruby支持功能強(qiáng)大的字符串操作和正則表達(dá)式檢索功能,可以方便的對(duì)字符串進(jìn)行處理。l 自動(dòng)垃圾收集具有垃圾回收(Garbage Collect,GC)功能,能自動(dòng)回收不再使用的對(duì)象。不需要用戶對(duì)內(nèi)存進(jìn)行管理。l 跨平臺(tái)和高度可移植性Ruby支持多種平臺(tái),在Windows, Unix,

19、Linux, MacOS上都可以運(yùn)行。Ruby程序的可移植性非常好,絕大多數(shù)程序可以不加修改的在各種平臺(tái)上加以運(yùn)行。l 有優(yōu)雅、完善的異常處理機(jī)制Ruby提供了一整套異常處理機(jī)制,可以方便優(yōu)雅地處理代碼處理出錯(cuò)的情況。l 擁有很多高級(jí)特性Ruby擁有很多高級(jí)特性,例如操作符重載、Mix-ins、特殊方法等等,是用這些特性可以方便地完成各種強(qiáng)大的功能。同時(shí),由于是解釋型語言,Ruby也有下列缺點(diǎn):l 解釋型語言,所以速度較慢l 靜態(tài)檢查比較少§1.4Ruby和Python的比較Python是Ruby的勁敵。其功力深厚,可謂“千年蛇妖”。但matz認(rèn)為Python的功能仍不完美,不然就不

20、會(huì)創(chuàng)造Ruby了。第二章 Ruby編程環(huán)境§2.1 Ruby的安裝Ruby支持多種平臺(tái),包括Windows、Linux、各種類UNIX、MacOS X等。§2.1.1在Windows 95/98/Me/XP上安裝Ruby對(duì)于使用Windows平臺(tái)的用戶,安裝Ruby是相當(dāng)簡單直接的事情。最方便的方法是使用“One-Click Ruby Installer”。不知你有沒有聽說過SourceForge?SourceForge 是全球最大的開放源代碼軟件開發(fā)平臺(tái)和倉庫。它集成了很多開放源代碼應(yīng)用程序,為軟件開發(fā)提供了整套生命周期服務(wù)。在Ruby世界,也有一個(gè)類似的網(wǎng)站,那就是Ru

21、byforge?!癘ne-Click Ruby Installer”是Rubyforge上的一個(gè)開源項(xiàng)目,也是Rubyforge上下載量最大的項(xiàng)目之一。這個(gè)項(xiàng)目將Ruby語言核心和一系列常用擴(kuò)展集成到了一起,還包含支持Ruby的免費(fèi)的IDE工具FreeRIDE和SciTE,除了這些之外還包括幫助文檔,示例代碼,RubyGems包管理器,F(xiàn)ox GUI庫,fxri(Interactive RubyHelp& Console)等。和正如它名字所示,使用它,Ruby安裝變得前所未見的容易。你可以在下面的地址下載到它的最新版本:/projects/ruby

22、installer/§2.1.2在Linux上安裝Ruby在linux下Ruby的安裝要稍微復(fù)雜一些,推薦使用源碼編譯的方式安裝,這樣可以保證安裝的是最新版本。首先到ruby主站/en/下載源代碼,下載完畢后解壓到目錄,然后使用以下命令:./configure./make; make install執(zhí)行上面的命令需要root權(quán)限,默認(rèn)安裝到/usr/local下。你也可以使用“./configure -prefix=自定義路徑”來指定安裝目錄。windows上的ruby one-click installer默認(rèn)安裝了RubyGems,但

23、在Linux下我們需要手動(dòng)安裝RubyGems。RubyGems是一個(gè)Ruby的包管理器,我們后邊會(huì)講到它。首先從Rubyforge下載RubyGems的最近版本,地址如下:/projects/rubygems/解壓RubyGems以后到相應(yīng)目錄下輸入ruby setup.rb,屏幕上打印一些日志以后會(huì)告訴你安裝成功,執(zhí)行g(shù)em -v可以查看gem安裝版本號(hào)。§2.2運(yùn)行Ruby下面,我們將以Windows平臺(tái)下的Ruby環(huán)境舉例如何運(yùn)行Ruby。§2.2.1使用Ruby將“Hello World”作為學(xué)習(xí)計(jì)算機(jī)語言第一個(gè)學(xué)寫的程序,現(xiàn)

24、在已經(jīng)成為一種傳統(tǒng)。該程序最早出現(xiàn)在由Brian Kernighan和Dennis Ritchie寫的經(jīng)典計(jì)算機(jī)程序設(shè)計(jì)教程The C Programming Language。我們來看看Ruby世界的“Hello World”:在Windows中,打開命令行提示符窗口,在提示符上輸入“Ruby”并回車,Ruby解釋器就會(huì)運(yùn)行并等候輸入程序。Ruby可執(zhí)行文件應(yīng)該包含在系統(tǒng)搜索路徑內(nèi)。輸入下面的程序:print "Hello World!"然后按Ctrl+D再按回車鍵,你就會(huì)看到Ruby執(zhí)行程序的輸出結(jié)果:你也可以先將代碼保存為文件,然后使用再Ruby解釋器執(zhí)行:§

25、;2.2.2 使用FreeRIDE和SciTEFreeRIDE是一個(gè)支持Ruby語言的免費(fèi)IDE環(huán)境。FreeRIDE本身就是使用Ruby語言開發(fā),它也是Rubyforge上的重要項(xiàng)目之一。可以使用FreeRIDE來編寫調(diào)試和執(zhí)行Ruby代碼,F(xiàn)reeRIDE內(nèi)置了交互式變成環(huán)境和Ruby語言在線幫助,功能十分強(qiáng)大。Scintilla是一個(gè)免費(fèi)的源代碼編輯控件,它完全開放源代碼,并允許用戶自由地用于開源軟件或是商業(yè)軟件中。SciTE是用這個(gè)控件開發(fā)了一個(gè)編輯軟件,在“One-Click Ruby Installer”中,SciTE集成了Ruby語言支持,使用起來非常方便。相比FreeRIDE,

26、它的特點(diǎn)就是使用簡單。§2.2.3 使用fxriFxri是一個(gè)Ruby交互幫助和控制臺(tái)工具。它不僅可作為語言的在線幫助,而且可以用作交互式Ruby解釋器來執(zhí)行程序。對(duì)于學(xué)習(xí)Ruby語言,fxri是一個(gè)非常方便的幫手。不知你有沒有聽說過FoxToolKit,它是相當(dāng)輕巧的開放源代碼的圖形庫。FXRuby是RubyForge上的一個(gè)項(xiàng)目,提供了Ruby語言使用Fox ToolKit的接口。而Fxri正是基于FXRuby開發(fā),F(xiàn)xri同樣是RubyForge上的項(xiàng)目。這樣你應(yīng)該可以猜到Fxri名字的由來JFxri同時(shí)集成了Ruby-irb和Ruby-ri的功能,有了它,你可以拋開Ruby-

27、irb,Ruby-ri了,但如果你用的不是Windows系統(tǒng)的話,算我沒說J§2.3Ruby-irbRuby-irb是交互式Ruby(Interactive Ruby)的簡稱,用來從標(biāo)準(zhǔn)輸入讀入并執(zhí)行Ruby代碼的工具,像一個(gè)shell。使用命令“irb”進(jìn)入交互式模式,然后可以象輸入命令行命令一樣輸入Ruby代碼,代碼執(zhí)行的結(jié)果會(huì)立刻顯示:§2.4Ruby-ri和Perl一樣,Ruby也設(shè)計(jì)了嵌入式文檔。 ruby-ri就是查看文檔的工具。Ruby-ri的執(zhí)行命令為“ri”,例如你可以通過“ri String.new”來查詢String類的new方法:§2.5R

28、ubyGemsRubyGems是Ruby社區(qū)流行的包管理工具,在以前如果要下載一個(gè)Ruby擴(kuò)展或者應(yīng)用程序的話,你需要先下載相應(yīng)的zip包,然后解壓縮,再將應(yīng)用或者擴(kuò)展安裝到Ruby對(duì)應(yīng)的目錄中。但是有了RubyGems所有這些麻煩都沒有了,你只需要一條命令就可以從遠(yuǎn)程服務(wù)器上下載相應(yīng)的包,如果相應(yīng)的應(yīng)用包含其他擴(kuò)展,RubyGems會(huì)提示你從遠(yuǎn)程安裝所依賴的擴(kuò)展。安裝后 RubyGems會(huì)運(yùn)行相應(yīng)的程序生成rdoc幫助文檔。當(dāng)然你也可以將軟件包下載到本地運(yùn)行RubyGems本地安裝命令。統(tǒng)一化的管理帶來的好處就是簡單,有了RubyGems包管理器,Ruby應(yīng)用的安裝將變得前所未見的容易。Ru

29、byGems是Rubyforge下載量最大的項(xiàng)目之一,現(xiàn)在Ruby社區(qū)的應(yīng)用都在朝著RubyGems的方向發(fā)展,RubyGems也將成為Ruby事實(shí)上的包管理器標(biāo)準(zhǔn)。RubyGems包管理器的可執(zhí)行命令是“gem”,gem命令包含很多子命令和相應(yīng)的選項(xiàng),例如:gem -h/-help 顯示命令幫助gem -v/-version 顯示Gems的版本號(hào)第三章 類與對(duì)象Ruby是一種真正的面向?qū)ο蟪绦蛟O(shè)計(jì)語言,面向?qū)ο笾敢詫?duì)象為中心的理論體系。l 封裝(Encapsulation)將內(nèi)部結(jié)構(gòu)和算法隱藏起來,以確保只有特定的過程(也叫方法)才能直接操作數(shù)據(jù),其結(jié)果是不能從外部直接使用數(shù)據(jù)構(gòu)造,同時(shí)一旦

30、內(nèi)部構(gòu)造發(fā)生變化也不會(huì)對(duì)外界造成不良影響。這種隔離方法就叫做封裝。l 繼承l(wèi) 多態(tài)(Polymorphism)根據(jù)對(duì)象的不同選擇合適的操作。在Ruby中的實(shí)現(xiàn)方法是,根據(jù)被調(diào)的對(duì)象的不同來選擇不同的方法。雖然有很多語言都宣稱自己是面向?qū)ο蟮?,但是他們往往?duì)面向?qū)ο蟮慕忉尪家粯樱蠖嗍且宰约禾赜械姆绞絹斫忉屖裁词敲嫦驅(qū)ο?,而在?shí)際情況中,這些面向?qū)ο笳Z言又采用了很多非面向?qū)ο蟮淖龇?。?Java 為例:如果你想取一個(gè)數(shù)字取絕對(duì)值,java 的做法是:int num = Math.abs(-99);也就是將一個(gè)數(shù)值傳遞給 Math 類的一個(gè)靜態(tài)函數(shù) abs 處理。為什么這么做?因?yàn)樵?java 中

31、,數(shù)值是基本類型不是類。而在 Ruby 中,任何事物都是對(duì)象,也就是說,數(shù)字99就是對(duì)象,取絕對(duì)值這樣的操作應(yīng)該屬于數(shù)字本身,所以Ruby的做法就是:c = -99.abs在Ruby中,你所操作的一切都是對(duì)象,操作的結(jié)果也是對(duì)象。§3.1 類的定義類是對(duì)具有同樣屬性和同樣行為的對(duì)象的抽象,Ruby中類的聲明使用class關(guān)鍵字。定義類的語法如下,class ClassNamedef method_name(variables)#some codeendend類的定義要在classend之間,在上面的格式中,ClassName是類名,類名必須以大寫字母開始,也就是說類名要是個(gè)常量。看下

32、面的例子:class Persondef initialize(name, gender, age)name = namegender = genderage = ageendend若某個(gè)類已經(jīng)被定義過,此時(shí)又用相同的類名進(jìn)行類定義的話,就意味著對(duì)原有的類的定義進(jìn)行追加。class Testdef meth1puts "This is meth1"endendclass Testdef meth2puts "This is meth2"endend在Test類中,原有meth1方法,我們又追加了meth2方法,這時(shí)候,對(duì)于Test類的對(duì)象,meth1和m

33、eth2同樣可用。§3.2 對(duì)象,屬性和方法類在實(shí)例化后生成對(duì)象,在強(qiáng)調(diào)對(duì)象歸屬于某類時(shí),有時(shí)候我們也使用實(shí)例對(duì)象一詞。方法(Method)是對(duì)對(duì)象進(jìn)行的操作。操作對(duì)象(被調(diào))以self來表示。在Ruby中,除去內(nèi)部類的對(duì)象以外,通常對(duì)象的構(gòu)造都是動(dòng)態(tài)確定的。某對(duì)象的性質(zhì)由其內(nèi)部定義的方法所決定??聪旅娴睦樱覀兪褂胣ew方法構(gòu)造一個(gè)新的對(duì)象,class Persondef initialize(name, gender, age)name = namegender = genderage = ageendendpeople = Person.new('Tom',

34、'male', 15)我們可以使用Person.new方法來創(chuàng)建一個(gè)Person類的實(shí)例對(duì)象。以打頭的變量是實(shí)例變量,他們從屬于某一實(shí)例對(duì)象,Ruby中實(shí)例變量的命名規(guī)則是變量名以開始,您只能在方法內(nèi)部使用它。initialize方法使對(duì)象變?yōu)椤熬途w”狀態(tài),initialize方法是一個(gè)特殊的方法,這個(gè)方法在構(gòu)造實(shí)例對(duì)象時(shí)會(huì)被自動(dòng)調(diào)用。對(duì)實(shí)例進(jìn)行初始化操作時(shí),需要重定義initialize方法。類方法new的默認(rèn)的行為就是對(duì)新生成的實(shí)例執(zhí)行initialize方法,傳給new方法的參數(shù)會(huì)被原封不動(dòng)地傳給initialize方法。另外,若帶塊調(diào)用時(shí),該塊會(huì)被傳給initializ

35、e方法。因此,不必對(duì)new方法進(jìn)行重定義。在Ruby中,只有方法可以操作實(shí)例變量,因此可以說Ruby中的封裝是強(qiáng)制性的。在對(duì)象外部不可以直接訪問,只能通過接口方法訪問。class Persondef namenameenddef gendergenderenddef ageageendendpeople = Person.new('Tom', 'male', 15)puts puts people.genderputs people.age輸出結(jié)果為:Tommale15在Ruby中,一個(gè)對(duì)象的內(nèi)部屬性都是私有的。上面的代碼中,我們定義了方法

36、name,gender,age三個(gè)方法用來訪問Person類實(shí)例對(duì)象的實(shí)例變量。注意name,gender,age訪問只能讀取相應(yīng)實(shí)例變量,而不能改變它們的值。我們也可以用成員變量只讀控制符attr_reader來達(dá)到同樣的效果。class Personattr_reader :name, :gender, :ageend類似地,我們可以定義方法去改變成員變量的值。class Persondef name=(name)name=nameenddef gender=(gender)gender=genderenddef age=(age)age=ageendendpeople = Person.

37、new('Tom', 'male', 15)= "Henry"people.gender= "male"people.age= 25也可以用成員變量寫控制符attr_writer來達(dá)到同樣的效果。class Personattr_writer :name, :gender, :ageend我們也可以使用attr_accessor來說明成員變量既可以讀,也可以寫。class Personattr_accessor :name, :gender, :ageend也可以使用attr控制符來控制變量是否可讀寫

38、。attr 只能帶一個(gè)符號(hào)參數(shù), 第二個(gè)參數(shù)是一個(gè) bool 參數(shù),用于指示是否為符號(hào)參數(shù)產(chǎn)生寫方法。它的默認(rèn)值是 false,只產(chǎn)生讀方法,不產(chǎn)生寫方法。class Personattr :name, true#讀寫attr :gender, true#讀寫attr :age, true#讀寫attr :id, false#只讀end注意attr_reader,attr_writer,attr_accessor和attr不是語言的關(guān)鍵字,而是Module模塊的方法。class Testattr_accessor :valueendputs Test.instance_methods - Te

39、st.superclass.public_methods執(zhí)行結(jié)果為:valuevalue=上面代碼中,我們使用Test.instance_methods得到Test類所有的實(shí)例方法,使用Test.superclass.public_methods得到Test父類所有的實(shí)例方法,然后相減就得到Test類不包含父類的所有的實(shí)例方法。由于instance_methods方法返回值為一個(gè)Array,所以我們作差值運(yùn)算,Array的具體操作后面章節(jié)會(huì)講到。也可以重定義方法,重定義一個(gè)方法時(shí),新的定義會(huì)覆蓋原有的定義。下面的例子重定義類中的方法meth1,class Testdef meth1puts &

40、quot;This is meth1"endenda = Test.newa.meth1class Testdef meth1puts "This is new meth1"endenda. meth1執(zhí)行結(jié)果為:This is meth1This is new meth1重定義同一個(gè)類時(shí),意味著對(duì)原有定義進(jìn)行補(bǔ)充,不會(huì)覆蓋原來的定義。而重定義方法時(shí),則會(huì)覆蓋原有定義。我們可以使用self標(biāo)識(shí)本身,self和Java中的this有些類似,代表當(dāng)前對(duì)象。class Persondef initialize(name, gender, age)name = nameg

41、ender = genderage = ageenddef <=>(other)self.age <=> other.ageendend<=> 方法通常意思為比較,返回值為-1,0或1分別表示小于,等于和大于。§3.3 繼承Ruby繼承的語法很簡單,使用 < 即可。class Student < Persondef initialize(name, gender, age, school)name = namegender = genderage = ageschool = schoolendendRuby語言只支持單繼承,每一個(gè)類都只

42、能有一個(gè)直接父類。這樣避免了多繼承的復(fù)雜度。但同時(shí),Ruby提供了mixin的機(jī)制可以用來實(shí)現(xiàn)多繼承。可以使用super關(guān)鍵字調(diào)用對(duì)象父類的方法,當(dāng)super省略參數(shù)時(shí),將使用當(dāng)前方法的參數(shù)來進(jìn)行調(diào)用。class Basedef meth(info)puts "This is Base #info"endendclass Derived < Basedef meth(info)puts "This is derived #info"superendendobj1 = Derived.newobj1.meth("test")執(zhí)行結(jié)

43、果為:This is derived testThis is Base test如果傳入的參數(shù)被修改再調(diào)用super的話,那么將會(huì)使用使用修改后的值。class Basedef meth(info)puts "This is Base #info"endendclass Derived < Basedef meth(info)puts "This is derived #info"info = "over"superendendobj1 = Derived.newobj1.meth("test")執(zhí)行結(jié)果為:

44、This is derived testThis is Base over§3.4 特殊方法與特殊類特殊方法是指某實(shí)例所特有的方法。一個(gè)對(duì)象有哪些行為由對(duì)向所屬的類決定,但是有時(shí)候,一些特殊的對(duì)象有何其他對(duì)象不一樣的行為,在多數(shù)程序設(shè)計(jì)語言中,例如C+和Java,我們必須定義一個(gè)新類,但在Ruby中,我們可以定義只從屬于某個(gè)特定對(duì)象的方法,這種方法我們成為特殊方法(Singleton Method)。class SingletonTestdef infoputs "This is This is SingletonTest method"endendobj1 =

45、SingletonTest.newobj2 = SingletonTest.newdef puts "This is obj2"執(zhí)行結(jié)果為:This is This is SingletonTest methodThis is obj2有時(shí)候,我們需要給一個(gè)對(duì)象定義一系列的特殊方法,如果按照前面的方法,那么只能一個(gè)一個(gè)定義: def obj2.singleton_method1enddef obj2.singleton_method2enddef obj2.singleton_method3enddef obj2.

46、singleton_methodnend這樣做非常繁復(fù)麻煩,而且無法給出一個(gè)統(tǒng)一的概念模型,因此Ruby提供了另外一種方法, class << objendobj是一個(gè)具體的對(duì)象實(shí)例,class << 代表它的特殊類。class SingletonTestdef meth1puts "This is meth1"enddef meth2puts "This is meth2"endendobj1 = SingletonTest.newobj2 = SingletonTest.newclass << obj2def me

47、th1puts "This is obj2's meth1"enddef meth2puts "This is obj2's meth2"endendobj1.meth1obj1.meth2obj2.meth1obj2.meth2執(zhí)行結(jié)果為:This is meth1This is meth2This is obj2's meth1This is obj2's meth2§3.5 類變量與類方法類變量被一個(gè)類的所有實(shí)例對(duì)象共享,也可以被類方法訪問到。類變量名以,開始,例如number。和全局變量,實(shí)例變量不同,類

48、變量在使用前必須初始化:class Personnumber = 0 #使用前必須有初值def initialize(name, gender, age)name = namegender = genderage = agenumber += 1endend類變量是私有的,在類外無法直接訪問,你只能通過實(shí)例方法和類方法去訪問它。同樣,類方法是屬于一個(gè)類的方法,定義類方法時(shí)需要在方法前加上類名:class Personnumber = 0 def initialize(name, gender, age)name = namegender = genderage = agenumber += 1

49、enddef Person.getNumber #類方法return numberendend除了Person.getNumber這種方式定義類方法外,還可以使用其它方式定義類方法,在后續(xù)章節(jié)可以陸續(xù)見到。§3.4 存取控制當(dāng)你設(shè)計(jì)一個(gè)類時(shí),你需要決定哪些屬性和方法可以在類外被訪問到,哪些屬性和方法在類外被隱藏。如果一個(gè)類有過多的屬性和方法在類外可以被訪問到,那么勢必破壞這個(gè)類的封裝性。幸運(yùn)的是在Ruby中,只能通過方法去改變一個(gè)類的屬性,這樣我們只需要考慮方法的存取控制。方法的存取控制有三種:l 公有方法(Public Method)n 方法在任何地方都可以被調(diào)用,這是方法的默認(rèn)存

50、取控制。除了initialize和initialize_cpoy方法,他們永遠(yuǎn)是私有方法。l 保護(hù)方法(Protected Method)n 方法只能被定義這個(gè)方法的類自己的對(duì)象和這個(gè)類的子類的對(duì)象所訪問。l 私有方法(private Method)n 方法只能被定義這個(gè)方法的類的對(duì)象自己訪問,即使是這個(gè)類的其他對(duì)象也不能訪問。Ruby中的保護(hù)方法和私有方法與一般面向?qū)ο蟪绦蛟O(shè)計(jì)語言的概念有所區(qū)別,保護(hù)方法的意思是方法只能方法只能被定義這個(gè)方法的類自己的對(duì)象和子類的對(duì)象訪問,私有方法只能被對(duì)象自己訪問。class Testdef method1 #默認(rèn)為公有方法endprotected#保護(hù)方

51、法def method2endprivate#私有方法def method3endpublicdef test_protected(arg) #arg是Test類的對(duì)象arg.method2 #正確,可以訪問同類其他對(duì)象的保護(hù)方法enddef test_private(arg)#arg是Test類的對(duì)象arg.method3 #錯(cuò)誤,不能訪問同類其他對(duì)象的私有方法endendobj1 = Test.newobj2 = Test.newobj1.test_protected(obj2)obj1.test_private(obj2)可以看到,和C+/Java相比,Ruby提供了更好的封裝性。也可以

52、使用以下更簡單的形式:class Testdef method1.enddef method2.enddef method3.enddef methdo4.endpublic:method1protected:method2private:method3, :method4endRuby和C+/Java的一個(gè)顯著不同是存取控制是程序運(yùn)行時(shí)決定的而不是靜態(tài)綁定的。所以只有在訪問一個(gè)受限制的方法時(shí)才會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤。§3.6 元類在Ruby中一切都是對(duì)象。類和實(shí)例對(duì)象都是對(duì)象。這句話聽起來有點(diǎn)拗口,讓我們來看一個(gè)例子:class Persondef initialize(name, ge

53、nder, age)name = namegender = genderage = ageendenda = Person.new('Tom', 'male', 15)puts a.object_id=>22429840puts Person.object_id=>22429960沒錯(cuò),類也是對(duì)象,這是Ruby和C+/Java的一個(gè)顯著不同,在C+/Java中,類僅僅是一個(gè)數(shù)據(jù)抽象,并沒有類也是對(duì)象這樣的概念。而在Ruby中存在著元類的概念,類也是對(duì)象,所有類都是元類的實(shí)例對(duì)象。和C+/Java相比,Ruby的面向?qū)ο蟪潭雀???梢钥吹?,類?duì)象和實(shí)例

54、對(duì)象一樣有自己的ojbect_id,你可以象調(diào)用一個(gè)實(shí)例對(duì)象的方法一樣去用它去調(diào)用類方法。所有類對(duì)象的類是Class類,Oject類是所有類的基類。irb(main):003:0> Object.class=> Classirb(main):004:0> Object.superclass=> nil這樣,我們可以從另一個(gè)角度去理解類變量與類方法,類變量就是一個(gè)類對(duì)象的實(shí)例變量,類方法就是指一個(gè)類對(duì)象類的特殊方法。類方法具體可分為兩種:第一種是在所有的類的父類Class中定義的,且被所有的類所共享的方法;第二種是各個(gè)類所特有的特殊方法。類方法中的self指的是類本身,這

55、點(diǎn)需要牢記,這樣我們可以使用多種方式定義類方法。class Test#定義類方法方式1def Test.meth1# .end#定義類方法方式2def self.meth2# .end#定義類方法方式3class << Testdef meth3# .endend#定義類方法方式4class << selfdef meth4# .endendend§3.7 Ruby的動(dòng)態(tài)性可以重新定義同一個(gè)方法,class RedefTestdef methputs "This is meth"endendobj1 = RedefTest.newobj1.

56、methclass RedefTestdef methputs "This is new meth"endendobj1.meth執(zhí)行結(jié)果為:This is methThis is new meth可以使用undef_method取消一個(gè)方法的定義,class UndefTestdef methputs "This is meth"endendobj1 = UndefTest.newobj1.methclass UndefTestundef_method(:meth)endobj1.meth執(zhí)行結(jié)果為:This is methtest.rb:14: un

57、defined method meth' for #<UndefTest:0x2ac8240> (NoMethodError)§3.8 變量變量名長度只受內(nèi)存大小的限制??梢酝ㄟ^區(qū)分Ruby變量名的首字符來區(qū)分它是局部變量、實(shí)例變量、類變量、全局變量還是常量。通常情況下,變量名的第二位字符以后是數(shù)字、字母或下劃線,但有的內(nèi)部變量名比較特殊,如“$?”。§3.8.1局部變量局部變量以小寫字母或下劃線開始。num = 1foo局部變量的作用域起始于聲明處,結(jié)束于該聲明所在的塊、方法定義、類模塊定義的結(jié)尾。2.times p defined?(num) num = 10 p num輸出為:nil10nil10即使聲明部分未被解釋器執(zhí)行仍有效,因?yàn)橐呀?jīng)經(jīng)過解釋器的處理。v = 1 if falsep defined?(v)p v輸出為:"local-variable"nil但若塊已經(jīng)變成過程對(duì)象的話,則局部變量將一直持續(xù)到該過程對(duì)象終結(jié)為止。若多個(gè)過程對(duì)象引用同一個(gè)作用域的話,局部變量將被這些對(duì)象所共享。(t

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論