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