Ruby語(yǔ)言中,以對(duì)象為基本單位,可以說(shuō)所有的元素都是對(duì)象。按照之前對(duì)于面向?qū)ο蟪绦虻睦斫?,?duì)象是指包含了特定屬性和方法集合的一組程序。對(duì)象由類來(lái)定義,具體的表現(xiàn)為對(duì)象實(shí)例。也就是說(shuō),對(duì)象是類的實(shí)例化[2]。
Ruby語(yǔ)言的基礎(chǔ)元素
對(duì)象:數(shù)值對(duì)象、字符串對(duì)象、正則表達(dá)式對(duì)象、時(shí)間對(duì)象、文件對(duì)象、目錄對(duì)象、數(shù)組、哈希、例外對(duì)象等
數(shù)值對(duì)象
由于Ruby中一切數(shù)據(jù)都是對(duì)象,所以我們處理的數(shù)字實(shí)際上也是對(duì)象。
a = 10,這樣一個(gè)簡(jiǎn)單的賦值語(yǔ)句,實(shí)際上應(yīng)當(dāng)理解為 a = Numeric.new(10) 這樣的一種實(shí)例化形式。
變量:局部變量(小寫(xiě)字母或_開(kāi)頭)、全局變量($)、實(shí)例變量(@)、類變量(@@)、虛擬變量。
Ruby中的變量在聲明時(shí),也不需要指定類型,這有點(diǎn)類似于弱類型語(yǔ)言的PHP。但是在變量被使用時(shí),他的類型就會(huì)被確定。
常量:以大寫(xiě)字母開(kāi)頭的變量就是常量
Ruby 中的保留字
Ruby中一般以換行來(lái)做為語(yǔ)句分割,也可以使用;來(lái)作為語(yǔ)義的分割符。在程序的書(shū)寫(xiě)過(guò)程中,我們要注意保持良好的書(shū)寫(xiě)風(fēng)格。
運(yùn)算符
操作運(yùn)算符
+、-、*、/、%、**
比較運(yùn)算符
>=、<=、==、<>、===
== 運(yùn)算符只能進(jìn)行兩個(gè)對(duì)象值的比較,如果要對(duì)對(duì)象進(jìn)行比較,則需要使用特定的方法 obj1.eql?(obj2),obj1.equal?(obj2)
對(duì)于數(shù)值對(duì)象,比較方法做了自定義,所以結(jié)果會(huì)有些不同。
Ruby中,對(duì)于返回True或False這種方法,命名上一般以?結(jié)尾,例如 def AreUSure?()。
邏輯運(yùn)算符
&&、||、and、or
位運(yùn)算符
&、|、~、^、>>、<<
Ruby中的真值與假值
Ruby中,在進(jìn)行判斷時(shí),false 和 nil 都為假,除此以外的所有值為真。nil 是一個(gè)特殊值,用于在正則表達(dá)式中表示沒(méi)有找到匹配的內(nèi)容。也就是說(shuō),0 在ruby中也是真值。
Ruby中的Symbol
在Ruby中Symbol表示“名字”,比如字符串的名字、標(biāo)識(shí)符的名字,創(chuàng)建一個(gè)Symbol對(duì)象的方法是在名字或者字符串之前加上":"。Ruby中每一個(gè)對(duì)象都有唯一的對(duì)象標(biāo)識(shí)符(Object Identifier),可以用object_id方法(Getter)獲得。
Ruby中的Block
代碼塊 Code Block 是Ruby的一個(gè)很強(qiáng)大的功能,同時(shí)又不是很容易理解其設(shè)計(jì)原理的一個(gè)元素。在《Programing Ruby》這本書(shū)中指出,block的存在可以用來(lái)實(shí)現(xiàn)Ruby中的一些Iterator,例如:
Array.each { |index| print Array[index] }
Block的定義方式有兩種,一種是{},另外一種是do/end。前一種比較適合編寫(xiě)單行程序時(shí)使用,后一種比較適合多行程序的情況。具體例子如下:
def greet(name)
print "Hello #{name} "
yield
end
greet("Wang") do
print "Hi"
end
Blcok必須跟在方法調(diào)用的后面,通過(guò)方法中的yield出發(fā)Block的執(zhí)行。
控制語(yǔ)句
條件判斷語(yǔ)句
在condition為真值時(shí),執(zhí)行對(duì)應(yīng)區(qū)塊的內(nèi)容。
if condition then
block 1
else
block 2
end
還可以有多個(gè)分支
if condition then
block 1
elsif condition then
block 2
else
block 3
end
Ruby中提供了一個(gè)與if相反的條件判斷語(yǔ)句 unless
unless condition then
block 1
else
block 2
end
分支判斷語(yǔ)句
case condition
when value1 then
block 1
when value2 then
block 2
else
block 3
end
值得一提的是,case語(yǔ)句中的判斷不僅僅只是變量數(shù)值的判斷,也可以使對(duì)象類型的判斷,也可以使正則表達(dá)式的判斷,所以Ruby的Case語(yǔ)句使用起來(lái),功能可以非常的強(qiáng)大。
循環(huán)控制語(yǔ)句
循環(huán)控制語(yǔ)句用在我們希望重復(fù)執(zhí)行一些動(dòng)作時(shí),使用循環(huán)控制語(yǔ)句,需要注意兩個(gè)要點(diǎn):一個(gè)是循環(huán)的條件、一個(gè)是循環(huán)的次數(shù)。
Ruby中提供了for、while、until三個(gè)循環(huán)控制語(yǔ)句,each、times、loop三個(gè)循環(huán)控制方法,我們可以根據(jù)需要選擇不同的方式。
while condition do
block 1
end
for variable in object do
block
end
until condition do
block
end
object.each{|variable|
block
}
Number.times { | index variable |
block
}
loop {
block
}
Ruby同時(shí)提供了三個(gè)循環(huán)控制的語(yǔ)句,包括:break、next、redo。
Ruby中的類、方法與模塊
Ruby中的類
類是對(duì)對(duì)象行為和屬性的描述。做為一門面向?qū)ο蟮哪_本語(yǔ)言,Ruby中支持類的概念,支持類的定義、繼承(不允許繼承多個(gè)父類)、限定方法的訪問(wèn)范圍、Setter和Getter的設(shè)置等。
類的定義
class ClassName
Version = "1.0"
attr_accessor :name
def initialize(parameter)
end
public
def publicMethod1
block
end
def publicMethod2
block
end
private
def privateMethod1
block
end
def privateMethod2
block
end
end
類的訪問(wèn)限定符
Ruby中提供了 public、private、protected 三個(gè)方法訪問(wèn)限定符,可以對(duì)單個(gè)或批量的方法制定訪問(wèn)的限制條件??梢詥为?dú)對(duì)單個(gè)方法進(jìn)行訪問(wèn)限定,也可以使用批量的方式對(duì)多個(gè)方法使用訪問(wèn)限定。
默認(rèn)情況下,所有的方法都是 public ,除了 initialize 之外,它始終是一個(gè) private 的方法。
類的繼承
class People
end
class Male < People
end
Ruby中的模塊
命名空間的概念?
模塊的定義
module moduleName
end
在其他文件中使用模塊時(shí),首先需要使用require將模塊文件包含進(jìn)來(lái),AutoLoad?。模塊可以在類中引入,這樣模塊的方法就會(huì)成為類的方法??梢允褂眠@個(gè)小技巧來(lái)實(shí)現(xiàn)Ruby的多重繼承。
Ruby中的方法(函數(shù))
Ruby中的方法區(qū)分為實(shí)例的方法、類的方法、函數(shù)性方法。其區(qū)分的依據(jù)為方法接收者的不同。
實(shí)例方法的使用方式,實(shí)例方法的定義實(shí)際上是在類中完成的。
object.method( argument1, argument2, argument3 )
類方法的使用方式
f = File.open( filename )
函數(shù)性方法的定義
def functionName( parameter1, parameter2 = "default value")
block
return
end
函數(shù)性方法可以省略 return 語(yǔ)句,這時(shí)函數(shù)的返回值就是方法中最后一個(gè)語(yǔ)句的值,就像 Perl 的處理一樣。省略 Return 語(yǔ)句可以為代碼書(shū)寫(xiě)帶來(lái)一些方便,但我們需要謹(jǐn)慎對(duì)待。
Ruby的函數(shù)可以返回多個(gè)值,例如:
a, b, c = funca()
錯(cuò)誤與例外處理
編寫(xiě)任何程序都可能會(huì)發(fā)生錯(cuò)誤,包括語(yǔ)法錯(cuò)誤、邏輯錯(cuò)誤。也可能會(huì)發(fā)生一些意外,比如說(shuō)硬件的意外損壞。所以我們?cè)诰帉?xiě)程序時(shí),要多所有可能發(fā)生的意外情況進(jìn)行考慮。在沒(méi)有例外處理的語(yǔ)言中,我們需要對(duì)每種可能發(fā)生錯(cuò)誤的情況進(jìn)行判斷。幸好,Ruby中提供了例外處理機(jī)制,它使我們的工作量大大的減輕了。
錯(cuò)誤處理的一般形式
begine
block
rescue=> ex
print ex.message
block
ensure
block
retry
end
Ruby中提供了 resuce 來(lái)在遇到例外時(shí)進(jìn)行錯(cuò)誤處理,ensure 確保不管在什么情況下它下面的代碼部分都會(huì)執(zhí)行,retry 重新嘗試從 begin 開(kāi)始的代碼。默認(rèn)情況下 $! 返回例外對(duì)象,$@ 返回例外信息。
Ruby 提供了 catch throw 的語(yǔ)法,但是這個(gè)和其他語(yǔ)言貌似區(qū)別很大。
Ruby提供了一個(gè)標(biāo)準(zhǔn)的例外類,其下有眾多的子類來(lái)表示不同的例外情況。
Ruby中常用的類
Numeric 類
Numeric類下包括了Integer、Fixnum、Bignum、Float四個(gè)子類,關(guān)系如下圖所示。
為了方便數(shù)學(xué)運(yùn)算,Ruby提供了Math模塊,可以方便的進(jìn)行三角函數(shù)等方面的公式運(yùn)算。
Array類
數(shù)組在任何語(yǔ)言中都是非常重要的一個(gè)元素,數(shù)組提供了一個(gè)數(shù)據(jù)的容器,讓我們可以通過(guò)索引快速的遍歷和訪問(wèn)需要的數(shù)據(jù)元素。
Ruby中的數(shù)組可以扮演三種角色:普通的索引數(shù)組、集合、隊(duì)列。借由這三種不同的使用方式,我們可以利用數(shù)組來(lái)實(shí)現(xiàn)FIFO、LILO等多種數(shù)據(jù)結(jié)構(gòu)。
數(shù)組的創(chuàng)建有多種方式:
1、使用 []。
2、使用 Array.new
3、類似于Perl的數(shù)組創(chuàng)建方式,使用%w進(jìn)行創(chuàng)建。
4、使用 obj.to_a 方法,將對(duì)象轉(zhuǎn)換為數(shù)組。
5、使用split方法,將字符串分割為數(shù)組。
Array類中提供了大量的函數(shù)方便進(jìn)行數(shù)組的操作,包括:arr.at(index)、arr.pop()、arr.push(value)、arr.shift()、arr.unshift(value)、arr.last()、arr.first()、arr.next()、
、arr.slice()、arr.values_at()、arr.concat()、a.compact()、a.compact!()、a.delete()、a.delete_at()、a.delete_if{|item| ... }、a.reject(|item|)、a.reject!(|item|)、a.slice!()、a.uniq()、a.uniq!()、a.collect{|item| ... }、a.collect!{|item| ... }、a.map{|item| ... }、a.map!{|item| ... }、a.fill()、a.fill(value,begin)、a.fill(value,begin,len)、a.fill(value, n..m)、a.flattern()、a.flattern!()、a.reverse()、a.reverse!()、a.sort()、a.sort!()、a.sort{|i,j| ... }、a.sort!{|i,j| ... }、a.sort_by(|i| ...)、等。
對(duì)于數(shù)組的遍歷,我們可以采用循環(huán)配合索引的方式,也可以采用Array提供的一些函數(shù)來(lái)實(shí)現(xiàn)。Array提供的函數(shù)中,有一類不會(huì)改變數(shù)組本身的內(nèi)容,這種方法稱為非破壞性方法,有一些方法會(huì)使數(shù)組的內(nèi)容發(fā)生改變,這類方法稱為破壞性方法。對(duì)于兩種方式都提供的函數(shù),一般在破壞性方法后加上!來(lái)進(jìn)行區(qū)分。我們?cè)谑褂脮r(shí),應(yīng)當(dāng)特別注意。
String類
字符串,是程序開(kāi)發(fā)中非常常見(jiàn)的一種數(shù)據(jù)類型。Ruby中,新建字符串的方式有:
1、直接使用"或者'新建
2、String.new新建
3、使用%Q和%q的方式新建
因?yàn)槎际抢^承自O(shè)bject類,所以和Array一樣,有一些公共的方法可以調(diào)用,比如is_a、delete、size、slice等方法(真的么?有點(diǎn)懷疑)。
字符串中,應(yīng)當(dāng)注意內(nèi)嵌表達(dá)式,例如 "a string is #{value}",和 內(nèi)嵌文檔 Here Document。這兩個(gè)方法,在PHP等腳本語(yǔ)言中也非常常見(jiàn),能夠?yàn)樘幚碜兞亢投嘈械奈谋据敵鰩?lái)很大的方便。
另外一個(gè)需要關(guān)心的問(wèn)題,就是字符串的編碼問(wèn)題。對(duì)于西歐文字,如果使用ASCII編碼,那么我們就可以認(rèn)為字符串的長(zhǎng)度,就等于存儲(chǔ)字符串的字節(jié)的長(zhǎng)度。但是在處理中文或其他類似文字時(shí),往往不能夠使用一個(gè)字節(jié)來(lái)存儲(chǔ)文字,所以字符串的長(zhǎng)度會(huì)同字節(jié)的長(zhǎng)度有不一致。
在程序開(kāi)發(fā)中,字符串處理常見(jiàn)的操作包括:去掉前后的空格(chomp)、去掉行尾的換行(strip)、查找字符串、替換字符串(sub、gsub、tr、正則等)、截取字符串(索引方式、函數(shù)方式)、計(jì)算字符串的長(zhǎng)度等。
Hash類
Hash做為一種數(shù)據(jù)結(jié)構(gòu),具有較快的存取速度,在處理一些Key-Value的場(chǎng)景中發(fā)揮重大的作用。
Ruby中的hash對(duì)象,創(chuàng)建方式包括:{}、Hash.new兩種。Hash的key理論上可以是任何對(duì)象,但是實(shí)際當(dāng)中,我們一般選擇Numberic、String、Date等做為key值,因?yàn)檫@樣的key值在比較中更為準(zhǔn)確,而其他的對(duì)象是否一致的比較則相對(duì)復(fù)雜。
Ruby中提供了獲取key、value的批量及迭代方式,方便我們獲取對(duì)象中的內(nèi)容。
正則表達(dá)式類(Regexp)
正則表達(dá)式的歷史可以追溯到科學(xué)家對(duì)人類神經(jīng)系統(tǒng)工作原理的早期研究。美國(guó)新澤西州的Warren McCulloch和出生在美國(guó)底特律的Walter Pitts這兩位神經(jīng)生理方面的科學(xué)家,研究出了一種用數(shù)學(xué)方式來(lái)描述神經(jīng)網(wǎng)絡(luò)的新方法,他們創(chuàng)新地將神經(jīng)系統(tǒng)中的神經(jīng)元描述成了小而簡(jiǎn)單的自動(dòng)控制元,從而作出了一項(xiàng)偉大的工作革新。
The origins of regular expressions lie in automata theory and formal language theory, both of which are part of theoretical computer science. These fields study models of computation (automata) and ways to describe and classify formal languages. In the 1950s, mathematician Stephen Cole Kleene described these models using his mathematical notation called regular sets.[1] The SNOBOL language was an early implementation of pattern matching, but not identical to regular expressions. Ken Thompson built Kleene's notation into the editor QED as a means to match patterns in text files. He later added this capability to the Unix editor ed, which eventually led to the popular search tool grep's use of regular expressions ("grep" is a word derived from the command for regular expression searching in the ed editor: g/re/p where re stands for regular expression[2]). Since that time, many variations of Thompson's original adaptation of regular expressions have been widely used in Unix and Unix-like utilities including expr, AWK, Emacs, vi, and lex.
正則表達(dá)式是為了進(jìn)行較為復(fù)雜的字符串匹配而出現(xiàn)的。
Ruby中,創(chuàng)建正則表達(dá)式對(duì)象有幾種方法://、Regexp.new()、%r等。
Ruby中正則表達(dá)式的元字符與其他語(yǔ)言中的正則表達(dá)式保持一致。
String類提供了sub、gsub、scan三個(gè)方法可以接收正則表達(dá)式對(duì)象。
IO類
IO是每個(gè)程序語(yǔ)言必不可少的部分,通常IO有三個(gè),標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出、錯(cuò)誤輸出。
對(duì)于Console來(lái)說(shuō),Ruby中使用$stdin、$stdout、$stderr來(lái)表示。
文件IO是我們平時(shí)編程中最常用到的一種。Ruby和其他語(yǔ)言一樣,提供了open、close、seek、popen、gets、readline、read等函數(shù)來(lái)幫助我們完成文件的讀取、修改、保存操作。
File和Dir類
IO類為我們提供了操作輸入、輸出的標(biāo)準(zhǔn)方法,但是對(duì)于我們平時(shí)經(jīng)常遇到的文件系統(tǒng)來(lái)說(shuō),對(duì)于文件和目錄的操作是我們經(jīng)常要進(jìn)行的,所以Ruby提供了File和Dir類,同時(shí)還提供了FileTest、fileutils等輔助類,來(lái)幫助我們更方便的進(jìn)行程序的編寫(xiě)。
Time、Date、DateTime類
如果不熟悉的人,看到這三個(gè)類,一定會(huì)問(wèn)為什么要這么多關(guān)于時(shí)間處理的類?
Ruby中的進(jìn)程與線程
Fiber、Thread、Process。
Fibers提供了掛起程序的一部分,然后執(zhí)行另外一部分程序的能力。實(shí)際上Fiber并不是完整意義上的多線程,因?yàn)槌绦虻膱?zhí)行會(huì)產(chǎn)生中斷,仍然是單條線索在執(zhí)行?;拘问饺缦拢?/p>
fiber = Fiber.new do
Fiber.yield 1
2
end
puts fiber.resume
Firber創(chuàng)建后,并不自動(dòng)運(yùn)行,而是等到Fiber#resume方法調(diào)用后,開(kāi)始執(zhí)行block內(nèi)的語(yǔ)句。遇到Fiber.yield后,暫停程序的執(zhí)行,直到下一次調(diào)用Fiber#resume或者程序執(zhí)行結(jié)束。
Thread。
在1.9之前,Ruby的多線程由解釋器實(shí)現(xiàn),在1.9之后,多線程開(kāi)始由系統(tǒng)來(lái)實(shí)現(xiàn)。但是由此帶來(lái)了一個(gè)問(wèn)題,很多Ruby的擴(kuò)展并不是Thread Safe的,所以有時(shí)候會(huì)遇到問(wèn)題,這個(gè)需要比較注意。Thread的創(chuàng)建方法。
threads = []
10.times{
threads << Thread.new(parameter) do |p|
end
}
threads.each{ |thr| thr.join }
Ruby中的工具
ri 文檔查看利器。通過(guò) ri options names 的方式,可以查看ruby的文檔,真是非常方便??!
irb 使用irb進(jìn)行交互式的編程。
參考資料:
1、Ruby Programming 高橋征義
4、Ruby Doc
7、Programming Ruby by Dave Thomas