国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄 搜尋
Ruby用戶指南 3、開(kāi)始 4、簡(jiǎn)單的例子 5、字符串 6、正則表達(dá)式 7、數(shù)組 8、回到那些簡(jiǎn)單的例子 9、流程控制 10、迭代器 11、面向?qū)ο笏季S 12、方法 13、類 14、繼承 15、重載方法 16、訪問(wèn)控制 17、單態(tài)方法 18、模塊 19、過(guò)程對(duì)象 20、變量 21、全局變量 22、實(shí)變量 23、局部變量 24、類常量 25、異常處理:rescue 26、異常處理:ensure 27、存取器 28、對(duì)象的初始化 29、雜項(xiàng) RGSS入門(mén)教程 1、什么是RGSS 2、開(kāi)始:最簡(jiǎn)單的腳本 3、數(shù)據(jù)類型:數(shù)字 4、數(shù)據(jù)類型:常量與變量 5、數(shù)據(jù)類型:字符串 6、控制語(yǔ)句:條件分歧語(yǔ)句 7、控制語(yǔ)句:循環(huán) 8、函數(shù) 9、對(duì)象與類 10、顯示圖片 11、數(shù)組 12、哈希表(關(guān)聯(lián)數(shù)組) 13、類 14、數(shù)據(jù)庫(kù) 15、游戲?qū)ο?/a> 16、精靈的管理 17、窗口的管理 18、活動(dòng)指令 19、場(chǎng)景類 Programming Ruby的翻譯 Programming Ruby: The Pragmatic Programmer's Guide 前言 Roadmap Ruby.new 類,對(duì)象和變量 容器Containers,塊Blocks和迭代Iterators 標(biāo)準(zhǔn)類型 深入方法 表達(dá)式Expressions 異常,捕捉和拋出(已經(jīng)開(kāi)始,by jellen) 模塊 基本輸入輸出 線程和進(jìn)程 當(dāng)遭遇挫折 Ruby和它的世界 Ruby和Web開(kāi)發(fā) Ruby Tk Ruby 和微軟的 Windows 擴(kuò)展Ruby Ruby語(yǔ)言 (by jellen) 類和對(duì)象 (by jellen) Ruby安全 反射Reflection 內(nèi)建類和方法 標(biāo)準(zhǔn)庫(kù) OO設(shè)計(jì) 網(wǎng)絡(luò)和Web庫(kù) Windows支持 內(nèi)嵌文檔 交互式Ruby Shell 支持 Ruby參考手冊(cè) Ruby首頁(yè) 卷首語(yǔ) Ruby的啟動(dòng) 環(huán)境變量 對(duì)象 執(zhí)行 結(jié)束時(shí)的相關(guān)處理 線程 安全模型 正則表達(dá)式 字句構(gòu)造 程序 變量和常數(shù) 字面值 操作符表達(dá)式 控制結(jié)構(gòu) 方法調(diào)用 類/方法的定義 內(nèi)部函數(shù) 內(nèi)部變量 內(nèi)部常數(shù) 內(nèi)部類/模塊/異常類 附加庫(kù) Ruby變更記錄 ruby 1.6 特性 ruby 1.7 特性 Ruby術(shù)語(yǔ)集 Ruby的運(yùn)行平臺(tái) pack模板字符串 sprintf格式 Marshal格式 Ruby FAQ Ruby的陷阱
文字

模塊 Modules



模塊是一種集中方法,類和常量的方法,主要帶來(lái)兩個(gè)好處:
  1. 模塊提供了一個(gè)命名空間(namespace )防止命名沖突。
  2. 通過(guò)模塊能實(shí)現(xiàn)混合插入(mixin)功能。

命名空間

當(dāng)你寫(xiě)的Ruby程序越來(lái)越大,越來(lái)越多之后,都會(huì)發(fā)現(xiàn)有很多代碼都可以重用,通??梢詫⑾嚓P(guān)例程組成一個(gè)庫(kù),分布到不同的文件以便被其它Ruby程序共享。

通常,這些代碼都以類的形式組織在一起,所以你可能將一個(gè)類或者和其相關(guān)的幾個(gè)類放到一個(gè)文件中。

但是,有時(shí)候你也許需要把一些不能在常理上認(rèn)為屬于一個(gè)類的東西組合到一起。

最初的辦法可能是將所有這些東西都放到一個(gè)文件中,然后在需要使用它的程序中引入這個(gè)文件,就像C語(yǔ)言那樣。但是,這樣做有一個(gè)問(wèn)題,比如你編寫(xiě)了一系列的三角函數(shù)sin,cos等,你將它們放到一個(gè)文件中,比如trig.rb,同時(shí),Sally也做著類似的工作,創(chuàng)建了自己的庫(kù)文件action.rb,包括自己的一些例程,其中有beGood和sin方法。Joe想編寫(xiě)一個(gè)程序,需要同時(shí)用到trig.rb和action.rb兩個(gè)文件,但是這兩個(gè)文件都定義了一個(gè)方法sin,這可不是什么好消息。

答案是模塊機(jī)制。模塊定義了一個(gè)命名空間,在這個(gè)空間里,你的方法和常量可以不必?fù)?dān)心和別人的重名,比如三角函數(shù)(trig)就可以放到一個(gè)模塊中:

module?Trig
??PI?=?3.141592654
??def?Trig.sin(x)
???#?..
??end
??def?Trig.cos(x)
???#?..
??end
end

然后Sally的方法可以放到另一個(gè)模塊:

 

module?Action
??VERY_BAD?=?0
??BAD??????=?1
??def?Action.sin(badness)
????#?...
??end
end

模塊中常量的命名和類中的一樣,以大寫(xiě)字母開(kāi)頭。方法定義也類似,模塊的方法定義和類方法定義類似,格式為mod_name.method_name。

如果第三個(gè)程序需要使用這些模塊,只需要簡(jiǎn)單的把這些模塊載入(使用Ruby的require語(yǔ)句,將在103頁(yè)討論),然后引用 限定的名字( qualified names)。

require?"trig"
require?"action"

 
y?=?Trig.sin(Trig::PI/4) 
wrongdoing?=?Action.sin(Action::VERY_BAD)
  

和類方法一樣,調(diào)用一個(gè)模塊方法也以這個(gè)模塊名字為前綴然后一個(gè)點(diǎn)再加上方法名;引用一個(gè)模塊的則是在模塊后面加兩個(gè)冒號(hào)再加常量。

 

混合插入(Mixins)

模塊還有一個(gè)非常有用的作用,即通過(guò)模塊使用叫做混合插入(mixin)的機(jī)制實(shí)現(xiàn)了多重繼承。

在上一節(jié)的例子里,我們定義了模塊方法,方法名前面加上了模塊名作為前綴。如果這樣讓你想到這是類方法,那么你可能會(huì)進(jìn)一步想“如果我在模塊里面定義實(shí)例變量會(huì)怎樣呢?”這個(gè)問(wèn)題非常好,一個(gè)模塊不能產(chǎn)生實(shí)例,因?yàn)樗皇穷?。但是,你可以在一個(gè)類的定義里包含(include )一個(gè)模塊,這時(shí)候,這個(gè)模塊中所有的實(shí)例方法都變成了在這個(gè)類所擁有(能使用)的方法了(all the module's instance methods are suddenly available as methods in the class as well)。這就叫做mixin,實(shí)際上,mix-in很像超類(superclasses)。

module?Debug
??def?whoAmI?
????"#{self.type.name}?(\##{self.id}):?#{self.to_s}"
??end
end
class?Phonograph
??include?Debug
??#?...
end
class?EightTrack
??include?Debug
??#?...
end
ph?=?Phonograph.new("West?End?Blues")
et?=?EightTrack.new("Surrealistic?Pillow")
ph.whoAmI? ? "Phonograph?(#537766170):?West?End?Blues"
et.whoAmI? ? "EightTrack?(#537765860):?Surrealistic?Pillow"

通過(guò)包含Debug模塊,PhonographEightTrack 都能訪問(wèn)whoAmI?實(shí)例方法。

關(guān)于include語(yǔ)句需要注意幾點(diǎn)。首先,這個(gè)語(yǔ)句和文件無(wú)關(guān),C程序員也使用預(yù)處理指令#include來(lái)將一個(gè)文件的內(nèi)容在編譯的時(shí)候加入到另一個(gè)文件。而Ruby的include語(yǔ)句只是創(chuàng)建了一個(gè)指向一個(gè)有名字的模塊的引用,如果這個(gè)模塊在一個(gè)獨(dú)立的文件中,那么你必須先用require將這個(gè)文件引入,然后才能使用include。第二,Ruby的include不是簡(jiǎn)單的將模塊的實(shí)例方法拷貝到類里面,而是建立一個(gè)從類到模塊的引用。如果很多個(gè)類都包含了同一個(gè)模塊,它們都指向同一樣?xùn)|西。如果你修改了模塊中一個(gè)方法的定義,即使你的程序還在運(yùn)行之中,你的類也能使用新的方法的行為[ 注意,我們這里說(shuō)的是實(shí)例方法,實(shí)例變量永遠(yuǎn)都是每個(gè)對(duì)象都有一份拷貝]

Mixin使得你能非常方便的給類增加方法,它的真正的強(qiáng)大之處在于能使模塊中的代碼和引入它的類中的代碼能相互作用。我們以標(biāo)準(zhǔn)的一個(gè)Ruby模塊Comparable 為例來(lái)說(shuō)明,這個(gè)模塊可以用來(lái)給類增加比較操作符(<,<= ,==,>=,>等)和between?方法。為了使得它能工作,Comparable 假設(shè)使用它的類都定義了 <=>操作符,所以作為類的創(chuàng)建者,你定一個(gè)<=>方法,,引入Comparable模塊,然后,你就免費(fèi)得到了6個(gè)其它的方法。在我們的Song類里,我們比較的基準(zhǔn)是歌曲的時(shí)長(zhǎng)。我們需要做的是增加<=>方法,和引入Comparable 模塊。

class?Song
??include?Comparable
??def?<=>(other)
????self.duration?<=>?other.duration
??end
end

然后,我們就可以檢查一下結(jié)果了,看看它的比較功能。

song1?=?Song.new("My?Way",??"Sinatra",?225)
song2?=?Song.new("Bicylops",?"Fleck",??260)
song1?<=>?song2 ? -1
song1??<??song2 ? true
song1?==??song1 ? true
song1??>??song2 ? false

最后,再看一下我們第43頁(yè)實(shí)現(xiàn)的Smalltalk的inject方法,我們可以把它改得更通用一些,通過(guò)使用一個(gè)能mixin的模塊。

module?Inject
??def?inject(n)
?????each?do?|value|
???????n?=?yield(n,?value)
?????end
?????n
??end
??def?sum(initial?=?0)
????inject(initial)?{?|n,?value|?n?+?value?}
??end
??def?product(initial?=?1)
????inject(initial)?{?|n,?value|?n?*?value?}
??end
end

然后,我們就可以用一些內(nèi)建類來(lái)測(cè)試一下:

 

class?Array
??include?Inject
end
[?1,?2,?3,?4,?5?].sum ? 15
[?1,?2,?3,?4,?5?].product ? 120

class?Range
??include?Inject
end
(1..5).sum ? 15
(1..5).product ? 120
('a'..'m').sum("Letters:?") ? "Letters:?abcdefghijklm"

更多的關(guān)于mixin的例子,可以參看403頁(yè)開(kāi)始的關(guān)于Enumerable 模塊的文檔。

 

Mixins中的實(shí)例變量(Instance Variables)

從C++轉(zhuǎn)到Ruby來(lái)的人經(jīng)常問(wèn)我們“在C++中,我們必須繞一些彎才能控制如何在多重繼承中共享實(shí)例變量,mixin中的實(shí)例變量會(huì)怎么樣呢?Ruby怎么處理這種情況呢?”

這對(duì)于初學(xué)者來(lái)說(shuō)不是什么大問(wèn)題,記住Ruby中的實(shí)例變量是如何工作的:以"@"作為前綴的變量作為當(dāng)前對(duì)象self的實(shí)例變量。

對(duì)于混合插入來(lái)說(shuō),你要引入的模塊可以在你的類里創(chuàng)建實(shí)例變量,并且可以用attr和friends來(lái)定義這些變量的訪問(wèn)器(accessor )。比如:

(For a mixin, this means that the module that you mix into your client class (the mixee?) may create instance variables in the client object and may use attr and friends to define accessors for these instance variables. )?

module?Notes
??attr??:concertA
??def?tuning(amt)
????@concertA?=?440.0?+?amt
??end
end

 
class?Trumpet  
??include?Notes  
??def?initialize(tune)  
????tuning(tune)  
????puts?"Instance?method?returns?#{concertA}"  
????puts?"Instance?variable?is?#{@concertA}"  
??end  
end
 
#?The?piano?is?a?little?flat,?so?we'll?match?it  
Trumpet.new(-5.3)
 
結(jié)果:
Instance?method?returns?434.7
Instance?variable?is?434.7

我們不僅訪問(wèn)了模塊中的方法,我們也可以訪問(wèn)它的實(shí)例變量。但是,這樣也會(huì)有一定的風(fēng)險(xiǎn),比如不同的模塊可能定義了一個(gè)同名的實(shí)例變量,從而產(chǎn)生了沖突。

module?MajorScales
??def?majorNum
????@numNotes?=?7?if?@numNotes.nil?
????@numNotes?#?Return?7
??end
end

 
module?PentatonicScales   
??def?pentaNum   
????@numNotes?=?5?if?@numNotes.nil?   
????@numNotes?#?Return?5?   
??end   
end
 
class?ScaleDemo   
??include?MajorScales   
??include?PentatonicScales   
??def?initialize   
????puts?majorNum?#?Should?be?7   
????puts?pentaNum?#?Should?be?5   
??end   
end
 
ScaleDemo.new
  
結(jié)果:
7
7

上面的兩個(gè)模塊中都定義了實(shí)例變量@numNotes,當(dāng)然程序最后的結(jié)果也與作者的期望的結(jié)果不同。

 

一般來(lái)說(shuō),mixin的模塊本身并不怎么攜帶實(shí)例數(shù)據(jù),它們使用訪問(wèn)器(accessors )來(lái)從對(duì)象取得數(shù)據(jù)。但是如果你想要?jiǎng)?chuàng)建一個(gè)必須要有自己狀態(tài)的模塊,請(qǐng)確定這個(gè)模塊的實(shí)例變量的名字要唯一,不要和其它模塊的重名(比如用模塊名作為變量名的一部分)

迭代器和模塊 Enumerable?

你應(yīng)該早就注意到了Ruby的集合類(collection classes)支持很多對(duì)它的處理:遍歷,排序等等,沒(méi)準(zhǔn)你也會(huì)想要是自己的類支持這么多優(yōu)秀的特點(diǎn)就更好了。

當(dāng)然,答案是肯定的,通過(guò)使用混合插入這個(gè)有用的機(jī)制和模塊Enumerable,你只需要再寫(xiě)一個(gè)名為each的迭代方法就可以了,在這個(gè)方法里,依次返回你自己的集合類的元素?;旌喜迦?code>Enumerable模塊,然后你的類就支持了比如map,include?,find_all?等方法了。如果你的集合里的元素對(duì)象支持<=>方法,那么你的這個(gè)集合也可以得到min,max,sort方法。

?

包含(Including)其它文件

因?yàn)槭褂肦uby輕松的能編寫(xiě)優(yōu)良的模塊化的代碼,你會(huì)經(jīng)常發(fā)現(xiàn)自己會(huì)寫(xiě)一些包含自包含的代碼,比如面向x的接口,用于y的算法等。一般的時(shí)候,我們會(huì)把這些文件作為類或者模塊的庫(kù)。

有了這些文件,如果你想把它們整合到你的新程序中,Ruby提供了兩種方法:

load?"filename.rb"

 
require?"filename"
  

load方法每次執(zhí)行都會(huì)包含一個(gè)Ruby源文件,而require只會(huì)包含一個(gè)文件一次,而且,require還有別的功能,它還能裝載共享二進(jìn)制的庫(kù)文件( load shared binary libraries)。這兩個(gè)方法都接收相對(duì)和絕對(duì)的文件路徑作為參數(shù),如果給的是相對(duì)路徑(或者只是一個(gè)文件名),系統(tǒng)將會(huì)在當(dāng)前的裝載路徑(load path)中的每個(gè)文件夾下尋找這個(gè)文件(裝載路徑保存在全局變量$:中,見(jiàn)140頁(yè)的討論)

使用load和require包含的文件也可以包含其它文件。其中需要注意的是require是一個(gè)可執(zhí)行的語(yǔ)句,它可以在一個(gè)if語(yǔ)句里使用,or it may include a string that was just built。包含時(shí)候的查找路徑也可以在運(yùn)行時(shí)候更改,你可以將需要的目錄加到$:,這是一個(gè)數(shù)組。

因?yàn)閘oad將無(wú)條件的裝載應(yīng)該源文件,你可以用它在運(yùn)行時(shí)候重新裝載一個(gè)可能在程序運(yùn)行之后更改過(guò)的文件。

5.times?do?|i|
???File.open("temp.rb","w")?{?|f|
?????f.puts?"module?Temp\ndef?Temp.var()?#{i};?end\nend"
???}
???load?"temp.rb"
???puts?Temp.var
?end
結(jié)果:
0
1
2
3
4


Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide"
Copyright ? 2001 by Addison Wesley Longman, Inc. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/)).

Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.

Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.
上一篇: 下一篇: