?
This document uses PHP Chinese website manual Release
由Alfred Aho(A)、Peter Weinberger(W)和Brian Kernighan(K)共通創(chuàng)建的一種小型腳本語(yǔ)言。
ml archive (blade/ruby)
進(jìn)行數(shù)據(jù)類(lèi)型變換的方法。如果某數(shù)值計(jì)算方法從參數(shù)那里獲得了一個(gè)類(lèi)型不明的實(shí)例時(shí), 它會(huì)調(diào)用coerce
方法來(lái)進(jìn)行數(shù)據(jù)類(lèi)型變換。coerce
方法會(huì)返回參數(shù)中的數(shù)值和本身。
Ruby庫(kù)的數(shù)值類(lèi)型變換順序?yàn)?/p>
Fixnum -> Bignum -> Rational -> Float -> Complex
該類(lèi)可將C中的指針處理成Ruby對(duì)象。由C指針、mark函數(shù)和free函數(shù)構(gòu)成。如果您想使用C語(yǔ)言來(lái)擴(kuò)充Ruby的功能的話, 就必須掌握該類(lèi)的使用方法。相反地, 如果您沒(méi)有這個(gè)打算的話, 它也就沒(méi)什么用了。
defined?
該操作符可以檢查某對(duì)象(表達(dá)式)是否已經(jīng)被定義。若未被定義就返回nil
,若已被定義,就以字符串形式返回它的種類(lèi)。雖然defined?
看似一個(gè)方法,實(shí)際上它是Ruby語(yǔ)法中的操作符, 它不會(huì)對(duì)參數(shù)進(jìn)行計(jì)算。因此下面的表達(dá)式
defined? print("abc\n")
不會(huì)輸出任何內(nèi)容。
面向?qū)ο蟮木幊陶Z(yǔ)言。據(jù)說(shuō),早先matz在讀了該語(yǔ)言作者所撰寫(xiě)的《Object-oriented Software Construction》之后頓覺(jué)恍然大悟。但奇怪的是Ruby與Eiffel卻并不相似。如果硬要找出雷同之處的話, 可能只有兩點(diǎn): 1.Ruby的塊以end
結(jié)尾;2.Ruby也有rescue
這個(gè)保留字。
end
該保留字表明了塊的結(jié)束。據(jù)統(tǒng)計(jì),大約有33%的人在看到這個(gè)end時(shí)會(huì)聯(lián)想起Pascal(純屬杜撰)。但它并不和begin連用,因此它可能更接近于Ada或Eiffel。
Ruby之所以不使用C和Perl中的{}
,主要是因?yàn)橐韵略?/p>
避開(kāi)單句·復(fù)句的問(wèn)題
例如在C語(yǔ)言中, 若想向下例中添加語(yǔ)句時(shí)
if (a==b) c();
如果寫(xiě)成這樣的話
if (a==b) c(); d();
就會(huì)造成難以發(fā)現(xiàn)的bug。即使是Pascal也存在這個(gè)問(wèn)題。
回避else
的問(wèn)題
與上例類(lèi)似, 如果寫(xiě)出下面這樣的語(yǔ)句的話
if (a==b) if (c==d) foo(); else bar();
就會(huì)引起混亂。其實(shí)它的本意應(yīng)該是
if (a==b) { if (c==d) foo(); else bar(); }
這個(gè)樣子。
提高可讀性
可能您對(duì)此持有異議, 但有的人認(rèn)為:用end來(lái)結(jié)束塊的做法可以提高程序的可讀性。
begin
和case
語(yǔ)法表達(dá)上的問(wèn)題
說(shuō)句實(shí)話,matz曾多次想把end用作變量。甚至探討過(guò)在ruby語(yǔ)法中添加{ }
的問(wèn)題,但因?yàn)闊o(wú)法完美地解決begin
和case
的語(yǔ)法表達(dá)的問(wèn)題,最終不得不放棄這個(gè)念頭??峙逻@才是最大的理由吧。
ENV
該對(duì)象的運(yùn)作方式與訪問(wèn)環(huán)境變量的Hash相同。實(shí)際上,它就是添加了特殊方法的Object類(lèi)的實(shí)例。使用該對(duì)象來(lái)修改環(huán)境變量后,其變化將會(huì)影響到Ruby的子進(jìn)程。
常見(jiàn)的問(wèn)題和解答。Ruby FAQ尚處于不斷完善的階段,問(wèn)題和解答是隨時(shí)更新的。
Ruby中沒(méi)有該語(yǔ)句。這并不是因?yàn)椤拔覀冇X(jué)得不應(yīng)該使用”goto,而是“實(shí)現(xiàn)其功能實(shí)在是太麻煩了”。實(shí)際上,您可以使用catch/throw
或異常來(lái)實(shí)現(xiàn)goto的功能。
main
頂層中的self。因?yàn)?code>self是必不可少的,所以它只是表明在頂層中有個(gè)Object
類(lèi)的實(shí)例--self而已。另外為了操作Object類(lèi),還特別定義了若干特殊方法。
已定義的特殊方法
Ruby的作者,也叫松本 行弘。請(qǐng)參考<URL:http://www.st.rim.or.jp/~fuku/cmail/>,另外,他還是3個(gè)孩子的父親。
就像在冰淇淋中混合多種配料可以做成美味的混合冰淇淋一樣,在類(lèi)中混合插入各種模塊就可以添加相應(yīng)的功能。請(qǐng)參考繼承。
matz堅(jiān)信濫用多重繼承會(huì)導(dǎo)致繼承關(guān)系的混亂,因此Ruby中不允許使用多重繼承。同時(shí)為充分發(fā)揮繼承功能的優(yōu)勢(shì),Ruby支持兩種繼承關(guān)系:1.使用is-a語(yǔ)句的繼承;2.使用Mix-in來(lái)共享并繼承模塊中的功能。
不必多說(shuō)了罷
Principle of least surprise
Ruby的勁敵。其功力深厚,可謂“千年蛇妖”。但matz認(rèn)為Python的功能仍不完美,不然就不會(huì)創(chuàng)造Ruby了。最要命的是Python限定了名稱(chēng)長(zhǎng)度(6個(gè)字符)。
Ruby Application Archive(RAA)
Ruby Change Request
Ruby Document
面向?qū)ο蟮哪_本語(yǔ)言。Ruby的意思是“緊跟在Perl(pearl是6月的誕生石,Ruby則是7月的誕生石)之后”。Ruby并不是其他單詞的縮寫(xiě)。
面向?qū)ο蟮木幊陶Z(yǔ)言。其實(shí)matz鐘愛(ài)Sather勝過(guò)Eiffel。但Ruby與Sather一點(diǎn)都不像。
self
表示被調(diào)的表達(dá)式。那為什么把它叫做self
呢?因?yàn)槿绻逊椒醋鲃?dòng)詞的話,那么被調(diào)就是該動(dòng)作的主語(yǔ),從方法的角度來(lái)看,被調(diào)當(dāng)然就是自己了。一般人認(rèn)為,Ruby對(duì)此并未深究,只不過(guò)是模仿Smalltalk的做法罷了。
面向?qū)ο蟮木幊陶Z(yǔ)言。它奠定了現(xiàn)代面向?qū)ο?理論體系的基礎(chǔ)。
super
在重定義的方法中調(diào)用上級(jí)方法。省略參數(shù)時(shí),將使用主調(diào)方方法的參數(shù)來(lái)進(jìn)行調(diào)用。
問(wèn)題:
修改參數(shù)中給出的數(shù)值后再調(diào)用super的話,將會(huì)使用原來(lái)的值還是修改后的值呢?
def foo(a) print a end def self.foo(a) a=25 super end foo(5) # 5 or 25??
答案:
使用修改后的值(25)
原為T(mén)hread of control的縮略語(yǔ),意指一系列的控制流。在Ruby中,一個(gè)程序內(nèi)可以同時(shí)存在若干線程。
undef
將方法設(shè)置為未定義狀態(tài)。繼承 和Mix-in的功能都是在類(lèi)中添加方法,而undef
則可以取消方法。但是,如果取消了類(lèi)所必需的方法(被其他方法所調(diào)用的方法)的話,其后果不堪設(shè)想。
方法的執(zhí)行主體。也就是方法調(diào)用表達(dá)式的`.
'中的左邊部分。在方法內(nèi),可以使用self來(lái)表示它。另外,您可以使用@變量名
的形式來(lái)訪問(wèn)被調(diào)的實(shí)例變量。
貼在對(duì)象上的標(biāo)簽。Ruby的變量包括全局變量、局部變量和實(shí)例變量。因?yàn)槌?shù)的值不能改變,所以不是變量。但它也是一種標(biāo)簽,因此在這一點(diǎn)上它與變量是相同的。
一旦定義了就不能再改變的變量。這個(gè)定義本身似乎就有點(diǎn)矛盾。
即指再定義。重新定義超類(lèi)或include模塊中已經(jīng)定義的方法。使用super即可調(diào)用原來(lái)的方法。
將數(shù)據(jù)構(gòu)造和對(duì)其進(jìn)行操作的過(guò)程封裝在一起,就形成了抽象數(shù)據(jù)類(lèi)型。對(duì)抽象數(shù)據(jù)進(jìn)行操作時(shí),必須使用封裝內(nèi)的操作才行。其結(jié)果是不能從外部直接使用數(shù)據(jù)構(gòu)造,同時(shí)一旦內(nèi)部構(gòu)造發(fā)生變化也不會(huì)對(duì)外界造成不良影響。我們把這個(gè)過(guò)程叫做封裝。
使對(duì)象(或“某事物”)變?yōu)椤熬途w”狀態(tài)。對(duì)實(shí)例進(jìn)行初始化操作時(shí),需要重定義Object#initialize方法。類(lèi)方法Class#new的默認(rèn)定義就是對(duì)新生成的實(shí)例執(zhí)行initialize
方法。傳給new
的參數(shù)會(huì)被原封不動(dòng)地傳給initialize
。另外,若帶塊調(diào)用時(shí),該塊會(huì)被傳給initialize
。
因此,不必對(duì)Class#new進(jìn)行重定義。
根據(jù)給出的條目即可查出對(duì)應(yīng)的定義。它是哈希表的別名。面向?qū)ο蟮氖甲髻刚逽malltalk把類(lèi)似哈希表的數(shù)據(jù)構(gòu)造稱(chēng)作“辭典”,所以時(shí)至今日仍然有一些人把哈希表稱(chēng)作辭典。
美洲大陸的原住民是Indian而并非Endian,那么這個(gè)Endian的詞源是什么呢?其實(shí)它出自Jonathan Swift寫(xiě)的《格列佛游記》。這本書(shū)中的人們因?yàn)槌噪u蛋的方法不同而分成兩類(lèi),從圓頭開(kāi)始吃的叫大Endian,從尖頭開(kāi)始吃的叫小Endian。在計(jì)算機(jī)業(yè)界,該詞表示CPU等排列數(shù)據(jù)的一種方式,據(jù)說(shuō)網(wǎng)絡(luò)一族的人們喜歡大Endian。請(qǐng)參考字節(jié)順序。
它并不是那種發(fā)生在break, next, redo, retry, return等方法的范圍內(nèi)的普通退出,而是一種跨度極大的退出。只要沒(méi)被捕捉到,它甚至?xí)龇椒ㄕ{(diào)用的牢籠來(lái)引發(fā)中斷。Ruby的大規(guī)模退出包括由異常引起的退出和catch/throw
。
大多數(shù)的異常(包括由exit
所引發(fā)的SystemExit
在內(nèi))都會(huì)被rescue 捕捉到。但是若該異常不值得捕捉(例:內(nèi)存分配失?。忉屍鞯腷ug)的話,就會(huì)放他一馬。
在catch/throw
中,通常會(huì)從被throw的地方起一直跳轉(zhuǎn)到與throw部分具有相同標(biāo)簽的catch部分為止。
即指調(diào)用帶塊方法。當(dāng)初為了進(jìn)行迭代操作而設(shè)置了帶塊方法,現(xiàn)在它仍然常被稱(chēng)作迭帶器。雖然可以將那些進(jìn)行迭代操作的方法叫做迭代器,但如果將所有帶塊方法的調(diào)用過(guò)程都看作迭帶器的話,勢(shì)必會(huì)引起混亂。
我們把那些可接受代碼段(塊)的方法叫做帶塊方法。調(diào)用帶塊方法就是指調(diào)用這些帶塊方法的過(guò)程。
在帶塊方法中使用yield就可以執(zhí)行塊的內(nèi)容。
當(dāng)然了,如何處理給出的塊,這完全取決于方法。所以,如果硬是把塊傳給一個(gè)不能帶塊的方法的話,也不會(huì)有什么結(jié)果,而且也不會(huì)發(fā)生錯(cuò)誤。
指在運(yùn)行時(shí)根據(jù)操作對(duì)象的數(shù)據(jù)類(lèi)型的不同來(lái)選擇合適的過(guò)程(方法)。它可以提高程序的靈活性。它是面向?qū)ο蟮谋匾獥l件之一。在Ruby中變量是沒(méi)有類(lèi)型的,因此必然可以進(jìn)行動(dòng)態(tài)綁定。
它是一種特殊的局部變量。Ruby的局部變量的作用域是固定的,因此在編譯時(shí)就會(huì)生成局部變量。動(dòng)態(tài)局部變量則有所不同,每次執(zhí)行時(shí)才會(huì)生成變量。在塊中首次被賦值的局部變量就是動(dòng)態(tài)局部變量,其作用域僅限于塊的內(nèi)部。這主要是為了讓各個(gè)Thread都能擁有自己獨(dú)立的變量而設(shè)的。
即指物體。舉個(gè)例子,“愛(ài)”可能不是對(duì)象,但“情書(shū)”卻是對(duì)象。甄別某事物是否屬于對(duì)象,這可能是個(gè)哲學(xué)問(wèn)題?;蛟S正因?yàn)槿绱?,面向?qū)ο笠沧兊脫渌访噪x起來(lái)。在計(jì)算機(jī)業(yè)界有人認(rèn)為對(duì)象就是指內(nèi)存中的特定空間。到底何謂對(duì)象,還真是個(gè)難題。另外,請(qǐng)參考封裝和抽象數(shù)據(jù)類(lèi)型。
根據(jù)對(duì)象的不同選擇合適的操作。在Ruby中的實(shí)現(xiàn)方法是,根據(jù)被調(diào)的對(duì)象的不同來(lái)選擇不同的方法。
例
obj = "abc" print obj.length, "\n" # => 3 obj = [1,2,3,4] print obj.length, "\n" # => 4
對(duì)對(duì)象進(jìn)行的操作。操作對(duì)象(被調(diào))以self來(lái)表示。在Ruby中,除去內(nèi)部類(lèi)的對(duì)象以外,通常對(duì)象的構(gòu)造都是動(dòng)態(tài)確定的。某對(duì)象的性質(zhì)由其內(nèi)部定義的方法所決定。
將內(nèi)部結(jié)構(gòu)和算法隱藏起來(lái),以確保只有特定的過(guò)程(也叫方法)才能直接操作數(shù)據(jù),這種隔離方法就叫做封裝。請(qǐng)參考抽象數(shù)據(jù)類(lèi)型。
在Ruby中,只有方法可以操作實(shí)例變量,因此可以說(shuō)Ruby中的封裝是強(qiáng)制性的。
哈希表的別名。因?yàn)楣1砜梢允褂萌我獾逆I來(lái)引出值,這就是“關(guān)聯(lián)”特性。另外,可以將哈希表看作是使用非數(shù)字形式索引的數(shù)組,這是它的“數(shù)組”特性,因此它也叫做“關(guān)聯(lián)數(shù)組”。以前是使用硬件來(lái)實(shí)現(xiàn)關(guān)聯(lián)數(shù)組(也叫關(guān)聯(lián)記憶)的功能的,但是隨著計(jì)算速度的攀升以及關(guān)鍵算法(叫做“哈希表”,它是現(xiàn)在的哈希表的詞源)的成功研發(fā),現(xiàn)在只用軟件就可以實(shí)現(xiàn)其功能了。
Ruby中的一種從鍵到值的映像(mapping)。也叫做關(guān)聯(lián)數(shù)組或辭典。哈希表之所以得此名,是因?yàn)樵趯?shí)現(xiàn)其功能時(shí)使用了一種叫做“哈希表”的算法。哈希的意思是“切碎”,是“hashed beef”中的“hash”。
嚴(yán)格地講,Ruby中沒(méi)有函數(shù)。但那些省略被調(diào)的方法調(diào)用看來(lái)確實(shí)很像函數(shù),而且有的方法根本不需要self或?qū)嵗兞康缺徽{(diào)信息,事實(shí)上后者已成為函數(shù)了。所以有時(shí)也就網(wǎng)開(kāi)一面地把這樣的方法叫成函數(shù)了。
通常將這種函數(shù)(式的方法)的方法可視性設(shè)成了private,這樣就只能以省略被調(diào)的形式來(lái)調(diào)用它們了。這類(lèi)方法中比較有代表性的是 模塊函數(shù)。
父進(jìn)程傳給子進(jìn)程的值。使用ENV就可以訪問(wèn)環(huán)境變量。傳給子進(jìn)程只是環(huán)境變量的副本,因此子進(jìn)程無(wú)法通過(guò)環(huán)境變量來(lái)向父進(jìn)程傳遞信息。這就好比老子不會(huì)聽(tīng)小孩的話一樣。
主要依賴(lài)于從祖先或親戚那里繼承的功能,而自己只做一些補(bǔ)充性的工作。在現(xiàn)實(shí)世界中,這種行為是要遭到唾棄的,但在計(jì)算機(jī)世界里這卻是個(gè)很經(jīng)濟(jì)的做法。繼承也可以指在某類(lèi)中添加新功能后生成一個(gè)新的類(lèi)。繼承可以用is-a的關(guān)系來(lái)加以詮釋。例如,如果您要生成一個(gè)“理科學(xué)生”類(lèi)的話,需要首先繼承描述一般學(xué)生特征的“學(xué)生”類(lèi),然后再添加“整天忙于應(yīng)付實(shí)驗(yàn)”等特征后即可生成該類(lèi)。若不存在is-a關(guān)系,而只想共享某些特性或功能時(shí),我們推薦您使用Mix-in。
腳本,特指由解釋器進(jìn)行處理的較短的程序。當(dāng)然了,其中也不乏大作。
腳本語(yǔ)言。
只能在特定范圍內(nèi)使用的變量。該范圍就是作用域。Ruby的作用域包括
幾種。只有塊能訪問(wèn)外側(cè)作用域的局部變量。局部變量的作用域 從該變量首次被賦值的位置起 直到該賦值位置所在的作用域結(jié)束為止。這個(gè)優(yōu)先范圍是靜態(tài)決定的,與具體的運(yùn)行情況無(wú)關(guān)。
可用來(lái)構(gòu)成循環(huán)或打家劫舍。
就是類(lèi)的方法??煞譃閮煞N:第一種是在所有的類(lèi)的超類(lèi)Class中定義的,且被所有的類(lèi)所共享的方法;第二種是各個(gè)類(lèi)所特有的特殊方法。這倒沒(méi)什么問(wèn)題。重要的是類(lèi)方法中的self
指的是類(lèi)本身,這點(diǎn)需要牢記。
實(shí)際的數(shù)值就保存在變量之中,這和引用是不同的。目前,Ruby中只有Fixnum、Symbol和nil/true/false是立即值。然而Ruby的某些版本并未將Fixnum算做立即值,這也無(wú)關(guān)緊要。在理論模型層面上,可以將所有的值都看作是對(duì)某對(duì)象的引用。
類(lèi)似于“思維方式”,這個(gè)詞很難說(shuō)得清楚。
以對(duì)象為中心的理論體系。英語(yǔ)中的"Object-Oriented"是個(gè)形容詞,可是到了日語(yǔ)中就變成名詞了。似乎只要將對(duì)象置于思考的中心點(diǎn)就萬(wàn)事大吉了,但也要兼顧一下幾點(diǎn)
多態(tài)
(或者動(dòng)態(tài)綁定)
有人甚至把它看作是包治百病的“魔法”,但事實(shí)上世界并非如此簡(jiǎn)單。面對(duì)對(duì)象概念誕生至今已逾20個(gè)年頭,它已經(jīng)磨礪成為一把實(shí)用的利劍。
以對(duì)象作為出發(fā)點(diǎn)的系統(tǒng)設(shè)計(jì)
以對(duì)象作為編程的中心。
以對(duì)象為根本的系統(tǒng)分析。
在那些函數(shù)式的方法中,模塊函數(shù)既可用作模塊的方法,又可用作特殊方法。例如Math模塊中的大部分方法都是模塊函數(shù)。您既可以這樣
Math.sqrt(2)
又可以這樣
include Math sqrt(2)
來(lái)使用它們。
這些內(nèi)部類(lèi)被嵌入Ruby解釋器內(nèi)部,其實(shí)例的結(jié)構(gòu)與普通對(duì)象有所不同。我們不建議您繼承內(nèi)部類(lèi)。Ruby的內(nèi)部類(lèi)如下所示(實(shí)際上遠(yuǎn)不止這些,更多詳情請(qǐng)參考內(nèi)部類(lèi)/模塊/異常類(lèi))
將對(duì)象依次排列。只要元素是可數(shù)的(include了Enumerable
)、且已定義了順序(定義了<=>)的話,Ruby就可以對(duì)這些元素的集合進(jìn)行排序。這并不僅限于數(shù)組,也適用于其他復(fù)雜對(duì)象的集合。
因?yàn)?font color="blue">String#chop!, Array#concat這種方法會(huì)直接改變被調(diào)的狀態(tài),因而會(huì)產(chǎn)生“破環(huán)性的作用”。不過(guò)您不必?fù)?dān)心,因?yàn)樗鼈儾粫?huì)損壞您的計(jì)算機(jī)。
在程序的各個(gè)角落中都可以使用的變量。比較危險(xiǎn),少用為佳。
即指對(duì)象。在強(qiáng)調(diào)對(duì)象歸屬于某類(lèi)時(shí),常使用實(shí)例這個(gè)詞。據(jù)說(shuō)有好多人因?yàn)椴涣私鈱?duì)象和實(shí)例的關(guān)系,因而搞不懂面對(duì)對(duì)象到底是怎么一回事兒。
對(duì)象所特有的變量。Ruby實(shí)例變量名前都有一個(gè)@
符號(hào),您只能在方法內(nèi)部使用它。
專(zhuān)屬于某特定對(duì)象的方法。請(qǐng)參考方法。在下列情況下,其他對(duì)象也可以繼承該特殊方法。
若在特殊方法中重定義了原先類(lèi)中的方法時(shí),可以使用super來(lái)調(diào)用原來(lái)的方法。
只對(duì)應(yīng)于某特定對(duì)象的假想類(lèi)。
matz最頭疼的就是寫(xiě)文檔了。他平時(shí)總是說(shuō)“源代碼就是文檔。連bug也寫(xiě)得清清楚楚”,當(dāng)然了誰(shuí)都不以為然。
開(kāi)始有10個(gè)人,后來(lái)越來(lái)越少。在計(jì)算機(jī)業(yè)界中,它是表示一種排列數(shù)據(jù)的形式。據(jù)說(shuō)有一家大的CPU制造商很喜歡小Endian。請(qǐng)參考字節(jié)順序。
遇到非正常情況就會(huì)引發(fā)異常。發(fā)生異常時(shí),只要沒(méi)使用begin中的rescue
進(jìn)行捕捉的話,它將跨越方法調(diào)用的阻攔,進(jìn)而中斷程序(thread)的運(yùn)行。有了異常處理功能之后,我們就不必再逐一檢查Ruby程序中的每個(gè)異常情況了。發(fā)生異常的地點(diǎn)信息被保存在$@中,而異常本身的信息被保存在$!中。
即指重定義。
將0x01020304
這4個(gè)字節(jié)數(shù)據(jù)按照1,2,3,4
或是4,3,2,1
的順序排列。前者叫做大Endian,而后者叫做小Endian。人們一直在爭(zhēng)論哪種方法更好,但至今尚無(wú)定論。