ruby語法基礎知識教程_第1頁
ruby語法基礎知識教程_第2頁
ruby語法基礎知識教程_第3頁
ruby語法基礎知識教程_第4頁
ruby語法基礎知識教程_第5頁
已閱讀5頁,還剩82頁未讀, 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

Ruby語言

GrantRen

hyqryq@gmail.com

2006年11月24日

-W.-X-

刖s

目錄

Ruby語言I

GrantReni

第一局部Ruby語言根基5

第一章Ruby語言概述5

§1.1Ruby的歷史5

§1.2Ruby名字的由來6

§1.3Ruby的特點6

§1.4Ruby和Python的比照6

第二章Ruby編程環境7

§2.1Ruby的安裝7

§2.1.1在Windows95/98/Me/XP上安裝Ruby7

§2.1.2在Linux上安裝Ruby7

§2.2運行Ruby7

§2.2.1使用Ruby7

§2.2.2使用FreeRIDE和SciTE8

§2.2.3使用fxri8

§2.3Ruby-irb8

§2.4Ruby-ri8

§2.5RubyGcms8

第三章類與對象9

§3.1類的定義9

§3.2對象,屬性和方法10

§3.3繼承12

§3.4特殊方法與特殊類13

§3.5類變量與類方法14

§3.4存取控制14

§3.6元類15

§3.7Ruby的動態性16

§3.8變量17

§3.8.1局部變量17

§3.8.2實例變量17

§3.8.3類變量18

§384全局變量18

§3.8.5常量18

§3.8與定義有關的操作19

§3.8.1alias19

§3.8.2undcf20

§3.8.3defincd?20

第四章根本類型22

§4.1Anay22

§4.2Hash23

§4.3Number23

§4.4String24

§4.5Rangc24

§4.6Symbol25

§4.7正則表達式26

第五章代碼塊和迭代器27

§5.1代碼塊(Block)27

§5.1.1什么是代碼塊27

§5.1.2代碼塊與對象27

§5.2迭代器(Iterator)28

§5.2.1什么是迭代器28

§5.2.2使用迭代器28

§5.2.3yield29

§5.2.4編寫自己的迭代器29

第六章表達式30

§6.1運算符30

§6.2命令替換31

§6.3賦值運算符32

§6.4并行賦值32

§6.5嵌套賦值33

§6.6其他賦值33

§6.7條件運算34

§6.8case表達式35

§6.9循環36

§6.9.1Loop36

§6.9.2While36

§6.9.3Unlil36

§6.9.4Iterator36

§6.9.5For..In37

§6.9.6Break.Redo,Next37

$6.9.7Retry39

第七章方法39

§7.1運算符重定義41

§7.2變長參數41

§7.3塊調用42

§7.4方法返回值42

第八章模塊43

§8.1名字空間43

§8.2mixin44

§8.3使用mixin44

§8.3.1Comparable44

§8.3.2Enumcrable45

§8.3.3Singlc(on46

§8.4Require,load和includc46

第九章異常47

§9.1異常處理47

§9.2定義異常類50

§9.3catch和throw51

第十章多任務處理51

§10.1多線程處理52

§10.1.1線程創立52

§10.1.2線程操作53

§10.1.3線程和異常53

§10.1.4線程調度55

§10.1.5線程同步55

§10.2多進程處理59

§10.2.1進程創立60

第十一章根本I/O操作60

§11.1使用Kernel模塊處理I/O操作61

§11.2文件處理61

§11.3StringIO61

§11.4Socket62

第十二章反射和對象空間62

§12.1ObjcctSpacc模塊62

§12.2觀察類和對象的狀態64

§12.3動態方法調用65

§12.3.1使用send方法65

§12.3.2使用Method類和UnboundMethod類65

§12.3.3使用eval方法67

§12.3.4性能67

§12.4Hook和回調方法68

§12.4.1什么是Hook68

§12.4.2Ruby中的Hook68

§11.4.2回調方法69

§12.5跟蹤程序的運行69

§12.5.1set_trace_func69

§12.5.2trace_var70

§12.5.3caller70

§12.5.3_FILE___LINE_和SCRIPT_LINES_70

第十三章序列化和YAML71

§13.1序列化的概念71

§13.2使用序列化71

§13.2.1二進制數據保存71

§13.2.2YAML數據保存71

§13.3定制序列化72

§13.3.1二進制數據保存72

§13.3.2YAML數據保存73

§13.3YAML73

§13.3.1集合類型74

§13.3.2單行集合類型76

§13.3.3根本類型76

§13.3.4塊77

§13.3.5別名和錨(AliasesandAnchors)77

§13.3.6文檔77

§13.3.7Ruby中YAML的使用77

第十四章安全控制77

§14.10級78

§14.11級78

§14.22級78

§14.33級78

§14.44級78

第十五章單元測試79

§15.1什么是單元測試79

§15.2Ruby單元測試框架79

第二局部內置類與模塊79

第一章內置類79

§1.1Array79

§1.2Bignum79

§1.3Binding79

§1.4Class79

§1.5Continuation79

§1.6Dir8l

§1.7ExceptionsI

§1.8FalseClass81

§1.9File8l

§1.10File::Stat81

§1.11Fixnum81

§LI2Float81

§1.13Hash81

§1.14Integers1

§1.151081

§1.16MatchData81

§1.17Meth()d81

§1.18ModulesI

§1.19NilClass81

§1.20Numeric81

§1.21Object82

§1.22Proc82

§1.23Process::Status82

§1.24Range82

§1.25Rcgexp82

§1.26String82

§1.27Struct82

§1.28Struct::Tms82

§1.29Symbol82

§1.30Thrcad82

§1.31ThreadGroup82

§1.32Timc82

§1.33TrueCiass82

§1.34UnhoundMethod82

第二章內置模塊82

§2.1Comparable83

§2.2Enumerable83

§2.3Error83

§2.4FileTest83

§2.5GC83

§2.6Kcrncl83

§2.7Marshal83

§2.8Ma(h83

§2.9Objcc(Spacc83

§2.10Process83

§2.11Process::GID83

§2.12Process::Sys83

§2.13Process::UID83

§2.14Signal83

第三局部Ruby語言總結84

附錄87

§1術語對照87

第一局部Ruby語言根基

第一章Ruby語言概述

§l.lRuby的歷史

Ruby語言的創造人是日本人松本行弘(MatsumotoYukihiro),大家親切的稱呼他"Malz"。

可能會出乎大家的意料,Ruby并不是一種近年來才誕生的語言,它的歷史可以追溯到1993年,Ruby之父

Matz開場對腳本語言感興趣.在通過?些分析和思考之后,Matz認為腳本語言是可以變得很強大和靈活的,

于是他準備把腳本語言作為他的開展方向。和很多人一樣,Malz是一個面向對象程序設計的fans,自然而

然他想研究一種支持面向對象程序設i?的腳本語言。隨后的一段時間,他到網絡上搜集了一些相關的資料,

并且發現了Perl5,當時Perl5還沒有發布。通過一段時間了解后,Matz.發現Perl5這并不是他想的東西,

所以他放棄了把Perl當作一個面向對象的腳本語言使用的念頭。隨后Matz轉向了Python,Python是一個解

新型的、面向對象語言,但是Matz發現Pylhon并不能完全算作“面向對象”語言。Malz認為Python是面

向對象和過程化程序設計語言(ProceduralProgrammingLanguage)的混合產物。Malz希望找到扁是一種比

Perl更強大、比Python更面向對象的語言,但是很遺憾,這樣的語言當時在地球上并不存在。于是Matz打

算自己設計一個全新的編程語言。1993年2月24日是一個值得紀念的日子,在這一天Ruby誕生了。1995

年12月Matz推出了Ruby的第一個版本Ruby0.95。在1996年以前,都是Matz.一個人在開發進展Ruby

的開發.后來隨著Ruby社區的漸漸形成.很多科I乂成員給了Malz許多有意義的幫助,包括提交hug和patch

等。現在,Ruby像其他開源工程一樣,有自己的開發團隊,任何有能力的個人或團體都可以參與Ruby的開

發與進化。

§1.2Ruby名字的由來

首先明確一點,Ruby并不是其他單詞的縮寫。受Perl的影響,Maiz也想用一種寶石來命名他的新語言,

他使用了他的一位同事的生肖石一紅寶石。后來,Matz意識到Ruby這個名字十分恰當,首先,在生肖石中,

Pearl代表六月,而Ruby代表七月。在字體大小上,Pearl大小是5pI,ruby的大小是5.5pi°所以Ruby這個名

字對于一種Perl的后續語言十分適宜。

§1.3Ruby的特點

Ruby是一種功能強大的面向對象的腳本語言,可以使用它方便快捷地進展面向對象程序設計。與Perl

類似,而且Ruby具有強大的文本處理功能,使文本處理變得簡單。此外匯可以方便地使用C語言來擴展Ruby

的功能。

假設您曾經“想要一種簡單的面向對象的語言",或者認為“Perl的功能雖然好用,但它的語法真讓人

受不了",又或者覺得“LISP系列語言的思想不錯,但到處都是括號真讓人討厭,最起碼算式應該按照通常

的樣式書寫"。那么,Ruby或許能讓您滿意。

歸納起來,Ruby有以下優點:

?解釋型執行,方便快捷

Ruby是解釋型語言,其程序無需編譯即可執行。

?語法簡單、優雅

語法比照簡單,類似Algol系語法。

?完全面向對象

Ruby從?開場就被設計成純粹的面向對象語言,因此所有東西都是對象,例如整數等根本數據類型。

?內置正則式引擎,適合文本處理

Ruby支持功能強大的字符串操作和正則表達式檢索功能,可以方便的對字符串進展處理。

?自動垃圾收集

具有垃圾回收(GarbageCollecl,GC)功能,能自動回收不再使用的對象。不需要用戶對內存進展管理0

?跨平臺和高度可移植性

Ruby支持多種平臺,在Windows,Unix,Linux,MacOS上都可以運行。Ruby程序的可移植性非常好,

絕大多數程序可以不加修改的在各種平臺上加以運行。

?有優雅、完善的異常處理機制

Ruby提供了一整套異常處理機制,可以方便優雅地處理代碼處理出錯的情況。

?擁有很多高級特性

Ruby擁有很多高級特性,例如操作符重載、Mix-ins、特殊方法等等,是用這些特性可以方便

地完成各種強大的功能。

同時,由于是解釋型語言,Ruby也有以下缺點:

?解釋型語言,所以速度較慢

?靜態檢查比照少

§1.4Ruby和Python的比照

Python是Ruby的勁敵。其功力深厚,可謂“千年蛇妖”。但matz認為Python的功能仍不完美,不然就

不會創造RubyTo

第二章Ruby編程環境

§2.1Ruby的安裝

Ruby支持多種平臺,包括Windows、Linux、各種類UNIX、MacOSX等。

§2.1.1在Windows95/98/Me/XP上安裝Ruby

對于使用Windows平臺的用戶,安裝Ruby是相當簡單直接的事情。最方便的方法是使用“One-ClickRuby

Installer*?

不知你有沒有聽說過SourceForgeSourceForge是全球最大的開放源代碼軟件開發平臺和倉庫。它集成了

很多開放源代碼應用程序,為軟件開發提供了整套生命周期服務。在Ruby世界,也有一個類似的網站,那

就是Rubyforge。"Onc-ClickRubyInsiallcr"是Rubyforgc上的一個開源工程,也是Rubyforge上下載量最大

的工程之一。這個工程將Ruby語言核心和一系列常用擴展集成到了一起,還包含支持Ruby的免費的IDE

J^FreeRIDE和SciTE,除了這些之外還包括幫助文檔,例如代碼,RubyGcms包管理器,FoxGUI摩,fxri

InteractiveRubyHelp&Console)等。和正如它名字所示,使用它,Ruby安裝變得前所未見的容易。你可以

在下面的地址下載到它的最新版本:

:〃ruby/Droiccls/rubyinstallni7

§2.1.2在Linux上安裝Ruby

在linux下Ruby的安裝要稍微復雜一些,推薦使用源碼編譯的方式安裝,這樣可以保證安裝的是最新版

本。

首先到ru到主站:〃rubY-/en/下載源代碼,下載完畢后解壓到目錄,然后使用以下命令:

./configure

./make;makeinstall

執行上面的命令需要root權限,默認安裝到/usMocal下。你也可以使用“./configure-prefix:自定義路徑”

來指定安裝目錄。

windows上的rubyonc-clickinstaller默認安裝了RubyGcms,但在Linux下我們需要于?動安裝RubyGcms。

RubyGems是一個Ruby的包管理器,我們后邊會講到它。

首先從Rubyforge卜載RubyGems的最近版本,地址如下:

://rubyforge.org/projccts/rubygems/

解樂RubyGems以后到相應目錄下輸入rubysetup.rb,屏幕卜.打印一些日志以后會告訴你安裝成功,執

行gem-v可以查看一gem安裝版本號。

§2.2運行Ruby

下面,我們將以Windows平臺下的Ruby環境舉例假設何運行Ruby。

§2.2.1使用Ruby

將“Hell。World"作為學習計算機語言第一個學寫的程序,現在己經成為一種傳統。該程序最早出現在

由BrianKcrnighan和DennisRitchie寫的經典計算機程序設計教程《TheCProgrammingLanguage》。我們來

看看Ruby世界的“HelloWorld":

在Windows中,硼開命令行提示符窗口,在提示符上輸入“Ruby”并回車,Ruby解新器就會運行井等

候輸入程序。Ruby可執行文件應該包含在系統搜索路徑內。

輸入下面的程序:

print"HelloWorld!"

然后按Ctrl+D再按回車鍵,你就會看到Ruby執行程序的愉出結果:

你也可以先將代碼保存為文件,然后便用再Ruby解釋器執行:

§2.2.2使用FreeRIDE和SciTE

FreeRlDE是一個支持Ruby語言的免費IDE環境。FreeRIDE本身就是使用Ruby語言開發,它也是

Rubyforge上的重要工程之一。

可以使用FreeRIDE來編寫調試和執行Ruby代碼,FreeRIDE內置了交互式變成環境和Ruby語言在線都

助,功能十分強大。

Scintilla是一個免費的源代碼編輯控件,它完全開放源代碼,并允許用戶自由地用于開源軟件或是商業

軟件中。SciTE是用這個控件開發了一個編輯軟件,在“One-ClickRubyInstaller”中,SciTE集成了Ruby語

言支持,使用起來非常方便。相比FreeRIDE,它的特點就是使用簡單。

§2.2.3使用fxri

Fxri是一個Ruby交互幫助和控制臺I;具。它不僅可作為語言的在線幫助,而且可以用作交互式Ruby解釋

器來執行程序。對于學習Ruby語言,fxri是一個非常方便的幫手。

不知你有沒有聽說過FoxToolKit,它是相當輕巧的開放源代碼的圖形庫。FXRuby是RubyForge上的一個工

程,提供了Ruby語言使用FoxToolKit的接口。而Fxri正是基于FXRuby開發,Fxri同樣是RubyForge上的工

程。這樣你應該可以猜到Fxri名字的由來怎

Fxri同時集成了Ruby-irb和Ruby-ri的功能,有了它,你可以拋開Ruby-irb,Ruby-ri了,但如果你用的

不是Windows系統的話,和我沒說⑥

§2.3Ruby-irb

Ruby-irb是交互式Ruby(InteractiveRuby)的簡稱,用來從標準輸入讀入并執行Ruby代碼的工具,像

一個shello

使用命令"irb”進入交互式模式,然后可以象輸入命令行命令一樣輸入Ruby代碼,代碼執行的結果會

立刻顯示:

§2.4Ruby-ri

和Perl一樣,Ruby也設計了嵌入式文檔。ruby-ri就是查看文檔的工具。Ruby-ri的執行命令為“ri”,

例如你可以通過“門JStnng.new"來查詢String類的new方法:

§2.5RubyGems

RubyGcms是Ruby社區流行的包管理工具,在以前如果要下載一個Ruby擴展或者應用程序的話,你需

要先下載相應的zip包,然后解壓縮,再將應用或者擴展安裝到Ruby對應的目錄中。但是有了RubyGems

所有這些麻煩都沒有了,你只需要一條命令就可以從遠程服務器上下載相應的包,如果相應的應用包含其他

擴展,RubyGems會提示你從遠程安裝所依賴的擴展。安裝后RubyGerrs會運行相應的程序生成rdoc幫助文

檔。當然你也可以將軟件包下載到本地運行RubyGems木地安裝命令。

統一化的管理帶來的好處就是簡單,有了RubyGems包管理器,Ruby應用的安裝將變得前所未見的容易。

RubyGems是Rubyforge下載量最大的匚程之一,現在Ruby社區的應用都在朝著RubyGems的方向開展,

RubyGcms也將成為Ruby事實上的包管理器標準。

RubyGems包管理器的口J"執行命令是“gem",gem命令包含很多子命令和相應的選項,例如:

gem-h/-help-顯示命令幫助

gem-v/—version-顯示Gems的版本號

第三章類與對象

Ruby是一種真正的面向對象程序設計語言,面向對象指以對象為中心的理論體系。

?封裝(Encapsulation)

將內部構造和算法隱藏起來,以確保只有特定的過程(也叫方法)才能直接操作數據,其結果是不能從外

部直接使用數據構造,同時一旦內部構造發生變化也不會對外界造成不良影響。這種隔離方法就叫做封裝。

?繼承

?多態(Polymorphism)

根據對象的不同選擇適宜的操作。在Ruby中的實現方法是,根據被調的對象的不同來選擇不同的方法。

雖然有很多語言都宣稱自己是面向對象的,但是他們往往對面向對象的解釋都一樣,大多是以自己特有

的方式來解釋什么是面向對象,而在實際情況中,這些面向對象語言又采用了很多非面向對象的做法。

以Java為例:如果你想取?個數字取絕對位,java的做法是:

in(num=Ma(h.abs(-99);

也就是將一個數值傳遞給Math類的一個靜態函數abs處理。為什么這么做因為在java中,數值是

根本類型不是類。

而在Ruby中,任何事物都是對象,也就是說,數字-99就是對象,取絕對值這樣的操作應該屬于數字

本身,所以Ruby的做法就是:

c=-99.abs

在Ruby中,你所操作的一切都是對象,操作的結果也是對象。

§3.1類的定義

類是對具有同樣屬性和同樣行為的對象的抽象,Kuby中類的聲明使用class關鍵字。定義類的語法如下,

classClassName

defmethod_name(variables)

#somecode

end

end

類的定義要在Sass…end之間,在上面的格式中,ClassName是類名,類名必須以大寫字母開場,也

就是說類名要是個常量。

看下面的例子:

classPerson

definitialize(name,gender,age)

?name=name

Qgender=gender

Gage=age

end

end

假設某個類已經被定義過,此時又用一樣的類名進展類定義的話,就意味著對原有的類的定義進展追加。

classTest

defmethl

puts"Thisismethl"

end

end

classTest

defmeth2

puts"Thisismeth2"

end

end

在Test類中,原有methl方法,我們又追加了meth2方法,這時候,對于Test類的對象,methl

和meth2同樣可用。

§3.2對象,屬性和方法

類在實例化后生.成對象,在強調對象歸屬丁某類時,有時候我們也使用實例對象一詞。

方法[Method)是對對象進展的操作。操作對象(被調)以self來表示。在Ruby中,除去內部類的對象以

外,通常對象的構造都是動態確定的。某對象的性質由其內部定義的方法所決定。

看下面的例子,我們使用new方法構造一個新的對象,

classPerson

definitialize(name,gender,age)

Qname=name

?gender=gender

?age=age

end

end

people=Person.new(*Tom','male',ib)

我們可以使用Person.ne翼方法來創立一個Person類的實例對象。以?打頭的變量是實例變量,他們

附屬于■某一實例對象,Ruby中實例變量的命名規則是變量名以@開場,您只能在方法內部使用它。

initialize方法使對象變為"就緒"狀態,initialize方法是一個特殊的方法,這個方法在構造

實例對象時會被自動調用。

對實例進展初始化操作時,需要重定義initialize方法。類方法new的默認的行為就是對新生成的

實例執行initialize方法,傳給new方法的參數會被原封不動地傳給initialize方法。另外,假設帶

塊調用時,該塊會被傳給initialize方法。因此,不必對new方法進展重定義。

在Ruby中,只有方法可以操作實例變量,因此可以說Ruby中的封裝是弗制性的。在對象外部不可以直

接訪問,只能通過接口方法訪問。

classPerson

defname

?name

end

defgender

?gender

end

defage

Gage

end

end

people=Person.new(1Tom','male*,15)

puts

putspeople.gender

putspeople.age

輸出結果為:

Tom

male

15___________________

在Ruby中,一個對象的內部屬性都是私有的,上面的代碼中,我們定義[史法name,gender,age三個

方法用來邁問Person類實例對象的實例變量。注意name,gender,age訪問只能讀取相應實例變量,而不能

改變它們的值。

我們也可以用成員變量只讀控制符attrreader來到達同樣的效果。

classPerson

attx_reader:name,:gender,:age

end

類似地,我們可以定義方法去改變成員變量的值。

classPerson

defname=(name)

@name=name

end

defgender=(gender)

@gender=gender

end

defage=(age)

@age=age

end

end

people=Person.new(*Tom','male*,15)

people.name="'Henry"

people.gender="male"

people.age=25

也可以用成員變量寫控制符attr_writer來到達同樣的效果。

classPerson

attr_writer:name,:gender,:age

end

我們也可以使用attjaccessor來說明成員變量既可以讀,也可以寫。

classPerson

attr_accessor:name,:gender,:age

end

也可以使用attr控制符來控制變量是否可讀寫。attr只能帶一個符號參數,第二個參數是一個bool

參數,用于指示是否為符號參數產生寫方法。它的默認值是false,只產生讀方法,不產生寫方法。

classPerson

attr:name,true#讀寫

attr:gender,true#讀寫

attr:age,true#讀寫

attr:id,false#只讀

end

注意attr_reader,attr_writer,attr_accessor和attr不是語言的關鍵字,而是Module

模塊的方法。

classTest

attr_accessor:value

end

putsTest.instance_methods-Test.superclass.public_methods

執行結果為:

value

value=

上面代碼中,我們使用Test.instance_methods得到rest類所有的實例方法,使用

Test.superclass.public_methods得至UTest父類所有的實例方法,然后相減就得到Test類不包含

父類的所有的實例方法。

由于instance_methods方法返回值為一個Array.所以我們作差值運算,Array的具體操作后而

章節會講到。

也可以重定義方法,重定義一個方法時,新的定義會覆蓋原有的定義。

下面的例子重定義類中的方法me二hl,

classTest

defmethl

puts"Thisismethl1'

end

end

a=Test.nevz

a.methl

classTest

defmethl

puts''Thisisnewmethl"

end

end

a.methl

執行結果為:

Thisismethl

Thisisnewmethl

重定義同一個類時,意味著對原有定義進展補充,不會覆蓋原來的定義。而重定義方法時,則會覆蓋原

有定義C

我們可以使用self標識本身,self和Java中的Ihis有些類似,代表當前對象。

classPerson

definitialize(name,gender,age)

?name=name

?gender=gender

@age=age

end

def<=>(other)

self.age<=>other.age

end

end

<=>方法通常意思為比照,返回值為0或1分別表示小于,等于和大于。

§3.3繼承

Ruby繼承的語法很簡單,使用<即可。

classStudent<Person

definitialize(name,gender,age,school)

@name=name

Qgender=gender

@age=age

^school=school

end

?nd

Ruby語言只支持單繼承,每一個類都只能有一個直接父類。這樣防止了多繼承的復雜度。但同時,Ruby

提供了mixin的機制可以用來實現多繼承。

可以使用super關鍵字調用對象父類的方法,當super省略參數時,將使用當前方法的參數來進展調

用。

classBase

defmeth(info)

puts"ThisisBase#{info}"

end

end

classDerived<Base

defmeth(info)

puts"Thisisderived#{info}',

super

end

end

obj1=Derived.new

obj1.meth("test")

執行結果為:

Thisisderivedtest

ThisisBasetest

如果傳入的參數被修改再調用super的話,那么將會使用使用修改后的值。

classBase

defmeth(info)

puts"ThisisBase#{info}*'

end

end

classDerived<Base

defmeth(info)

puts*'Thisisderived#{info)"

info="over"

super

end

end

obj1=Derived.new

obj1.meth("test")

執行結果為:

Thisisderivedtest

ThisisBaseover

§3.4特殊方法與特殊類

特殊方法是指某實例所特有的方法。一個對象有哪些行為由對向所屬的類決定,但是有時候,一些特殊

的對象有何其他對象不一樣的行為,在多數程序設計語言中,例如C++和Java,我們必須定義一個新類,但

在Ruby中,我們可以定義只附屬于某個特定對象的方法,這種方法我們成為特殊方法(SingletonMethod)。

classSinqletonTest

definfo

puts"ThisisThisisSingletonTestmethod"

end

end

obj1=SingletonTest.new

obj2=SingletonTest.new

defobj2.info

puts"Thisisobj2n

end

obj1.info

obj2.info

執行結果為:

ThisisThisisSingletonTestmethod

Thisisobj2

芍時候,我們需要給一個對象定義一系列的特殊方法,如果按照前面的方法,那么只能一個一個定義:

defobj2.singleton_methodl

end

defobj2.singleton_method2

end

defobj2.singleton_method3

end

defobj2.singleton_methodn

end

這樣做非常繁復麻煩,而且無法給出一個統一的概念模型,因此Ruby提供了另外一種方法,

class<<obj

end

obj是一個具體的對象實例,class?代表它的特殊類。

classSingletonTest

defmethl

puts"Thisismethl"

end

defmeth2

puts''Thisismeth2"

end

end

obj1=SingletonTest.new

obj2=SingletonTest.new

class<<obj2

defmethl

puts"Thisisobj2*smethl"

end

defmeth2

puts"Thisisobj2*smeth2u

end

end

obj1.methl

obj1.meth2

obj2.methl

obj2.meth2

執行結果為:

Thisismethl

Thisismeth2

Thisisobj21smethl

Thisisobj2*smeth2

§3.5類變量與類方法

類變量被一個類的所有實例對象共享,也可以被類方法訪問到,類變量名以開場,例如

和全局變量,實例變量不同,類變量在使用前必須初始化:

classPerson

@@number=0#使用前必須有初值

definitialize(name,gender,age)

Gname=name

@gender=gender

Gage=age

@?number+=1

end

end

類變量是私有的,在類外無法直接訪問,你只能通過實例方法和類方法去訪問它。

同樣,類方法是屬于一個類的方法,定義類方法時需要在方法前加上類名:

classPerson

??number=0

definitialize(name,gender,age)

0name=name

?gender=gender

@age=age

◎?number+=1

end

defPerson.getNumber#類方法

return@?number

end

end

除了Person.getNumber這種方式定義類方法外,還可以使用其它方式定義類方法,在后續章節可以

陸續見到。

§3.4存取控制

當你設計?個類時,你需要決定哪些屬性和方法可以在類外被訪問到,哪些屬性和方法在類外被隱藏。

如果一個類有過多的屬性和方法在類外可以被訪問到,那么勢必破壞這個類的封裝性。幸運的是在Ruby中,

只能通過方法去改變一個類的屬性,這樣我們只需要考慮方法的存取控制。

方法的存取控制有三種:

?公有方法(PublicMethod)

■方法在任何地方都可以被調用,這是方法的默認存取控制。除了initialize和

initialize_cpoy方法,他們永遠是私有方法。

?保護方法(ProtectedMethod)

■方法只能被定義這個方法的類自己的對象和這個類的子類的對象所訪問。

?私有方法(privateMethod)

■方法只能被定義這個方法的類的對象自己訪問,即使是這個類的其他對象也不能訪問。

Ruby中的保護方法和私有方法與一般面向對象程序設計語言的概念有所區別,保護方法的意思是方法

只能方法只能被定義這個方法的類自己的對象和子類的對象訪問,私有方法只能被對象自己訪問。

classTest

defmethodi#默認為公有方法

end

protected#保護方法

defmethod2

end

private#私有方法

defmethods

pnd

public

deftest_protected(arg)#arg是Test類的對象

arg.method24正確,可以訪問同類其他對象的保護方法

end

deftest_private(arg)#arg是Test類的對象

arg.n^thod3#錯誤,不能訪問同類其他對象的私有方法

end

end

obj1=Test.new

obj2=Test.new

obj1.test_protected(obj2]

obj1.test._privat.e(obj2)

可以看到,和C+1/Java相比,Ruby提供了更好的封裝性。

也可以使用以下更簡單的形式:

classTest

defmethodi

end

defmethod2

end

defmethod3

end

defmethdo4

end

publicimethodl

protected:method2

private:method3z:method4

end

Ruby和C++/Java的一個顯著不同是存取控制是程序運行時決定的而不是靜態綁定的。所以只有在訪問

一個受限制的方法時才會產生運行時錯誤。

§3.6元類

在Ruby中一切都是對象。類和實例對象都是對象。這句話聽起來有點拗口,讓我們來看一個例子:

classPerson

definitialize(name,gender,age)

Qname=name

Ggender=gender

Cage=age

end

end

a=Person.new(*Tom1,'male',15)

putsa.object_id=>22429840

putsPerson.object_id=>22429960

沒錯,類也是時象,這廷'Ruby和C++/Java的一個顯著不同,在C++/Java中,類僅僅是一個數據

抽象,并沒有類也是對象這樣的概念。而在Ruby中存在著元類的概念,類也是對象,所有類都是元類的實

例對象。和C++/Java相比,Ruby的面向對象程度更高。

可以看到,類對象和實例對象一樣有自己的ojbect_id,你可以象調用一個實例對象的方法一樣去用

它去調用類方法。所有類對象的類是Class類,Oject類是所有類的基類。

irb(main):003:0>Object.class

=>Class

irb(main):004:0>Object.superclass

=>nil

這樣,我們可以從另?個角度去理解類變量與類方法.類變量就是?個類對象的實例變量,類方法玳是

指一個類對象類的特殊方法。

類方法具體可分為兩種:第一種是在所有的類的父類Class中定義的,且被所有的類所共享的方法:第

二種是各個類所特有的特殊方法。

類方法中的self指的是類本身,這點需要牢記,這樣我們可以使用多種方式定義類方法。

classTest

北定義類方法方式1

defTest.methl

#...

end

步定義類方法方式2

defself.meth2

?…

end

年定義類方法方式3

class?Test

defmeth3

#...

end

end

#定義類方法方式4

class<<self

defmeth4

#...

end

end

end

§3.7Ruby的動態性

可以重新定義同一個方法,

classRedefTest

defmeth

puts"Thisismeth”

end

end

OJDJ1=RedetTest.new

obj1.meth

classRedefTest

defmeth

puts"Thisisnewmeth”

end

end

obj1.meth

執行結果為:

Thisismeth

Thisisnewmeth

可以使用undef_method取消?個方法的定義,

classUndefTest

defmeth

puts"Thisismeth”

end

end

obj1=UndefTest.new

obj1.meth

classUndefTest

undef_method(:meth)

end

obj1.meth

執行結果為:

Thisismeth

test.rb:14:undefinedmethod'meth*for#<UndefTest:0x2ac8240>(NoMethodError)

§3.8變量

變量名長度只受內存大小的限制??梢酝ㄟ^區分Ruby變量名的首字符來區分它是局部變量、實例變量、

類變量、全局變量還是常量。通常情況下,變量名的第二位字符以后是數字、字母或下劃線,但有的內部變

量名比照特殊,如。

§3.8.1局部變量

局部變量以小寫字母或下劃線開場。

num=1

foo

局部變量的作用域起始于聲明處,完畢于該聲明所在的塊、方法定義、類/模塊定義的結尾。

2.times{

pdefined?(num)

num=10

pnum

}

輸出為:

nil

10

nil

10

即使聲明局部未被解釋器執行仍有效,因為已經經過解釋器的處理。

v=1iffalse

pdefined?(v)

Pv

輸出為:

"local-variable**

nil

但假設塊已經變成過程對象的話,則局部變量將一直持續到該過程對象終結為止。假設多個過程對

象引用同一個作用域的話,局部變量將被這些對象所共享。

(to-do例子)

§3.8.2實例變量

以@開場的變量是實例變量,實例變量屬于特定的對象。

classPerson

definitialize(name,gender,age)

?name=name

Qgender=gender

Gage=age

end

end

上面的例子中,@name,@gender,@age都是實例變量。可以在類或子類的方法中引用實例變量.假

設引用尚未被初始化的實例變量的話,其值為nil.

§3.8.3類變量

以@@開場的變量是類變量c類變量在類的定義中定義.可以在類

溫馨提示

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

評論

0/150

提交評論