ruby self與作用域

self

ruby是完全的面向對象的語言,程序的執行依賴於對象系統。ruby編程的一個基石是默認對象或是說當前對象,在程序中可以通過關鍵字self訪問。在程序執行的任意時刻都有且只有一個self對象。

總 是有且只有一個當前對象self。self代表當前程序的執行上下文環境,否則脫離了上下文程序將失去意義。每種上下文中都有着同一並且唯一的self對 象。在ruby當中一共有四種上下文。頂層會產生一個上下文,出了頂層上下文,class module def三個定義關鍵字會產生類定義上下文、模塊定義上下文以及方法定義上下文三種定義上下文。其中方法定義上下文包括實例方法定義上下文、類方法定義上下 文和單例方法定義上下文,但它們本質是一樣的。

1.頂層self對象

在任何類或模塊定義塊之外的程序代碼都 屬於頂層。ruby爲頂層構建了一個main對象,賣弄對象是object的實例,頂層的self對象即是main對象。但是卻不能直接引用main對 象,一般也幾乎無需引用main對象。倘若有需要引用賣弄對象可以通過m = self將main對象賦值給一個變量。

頂層機制讓ruby實現像c語言一樣的面向過程編程方式,確實比較強大!

2.在類和模塊定義總的self

在 類或模塊定義中,self是類對象或模塊對象。這個規則很重要,因爲在ruby當中一切都是對象。類和模塊自然也是對象。在類和模塊中除了定義方法外,還 是個可執行的上下文,也就是說在類或模塊的定義體中還可以執行代碼,這使得ruby的類和模塊具有異常強大的功能。你甚至剛剛在類中定義一個類方法,隨後 馬上在類體定義體中執行這個類方法。

3.在實例方法定義中的self

當解釋器遇到一個def end塊時立即定義一個方法,但此時卻不執行。ruby中一切都是對象,從這個方面來說ruby中只有實例方法,方法都是存儲在該對象所屬的類中。而所謂 的類方法都是存儲在該類對象所屬的單例類中。方法被調用時,實例方法定義中的self是此時調用此方法的對象。

4.在單例方法或類方法定義中的self

單例方法與類方法跟實例方法其實本質一致。單例方法存儲在對象的單例類中,而單例方法只能由這個對象調用,故單例方法中的self對象是該對象。類方法中的self也是調用此類方法的對象,一般來說self是該類對象。

如 果存在同名的方法和變量,而且使用裸詞,那麼變量具有優先權。ruby解釋器會先將該裸詞解釋爲變量,若此變量爲定義則解釋爲方法,要是該方法也沒有定義 則出錯。因該避免出現命名衝突。如果以及存在命名衝突的時候,調用方法時應該帶上方法的接受者(對象點號符)或者是括號。

ruby中很重要的一條規則:在ruby程序中出現的任何實例變量,都屬於該程序中該位置的當前對象self。

作用域

ruby 有五種類型的變量,分別是類變量、實例變量、常量以、全局變量及局部變量。ruby中的變量是採用命名約定來定義變量類型的。以@@開頭的爲類變量,以@開頭的爲實 例變量,第一字母大寫的爲常量。類名和模塊名也是常量,類名和模塊名的命名約定爲駝峯式,單詞之間相互連接在一起,並且每個單詞第一個字母都大寫。而普通 常量每個字母都大寫,單詞之間用下劃線連接。全局變量以$開頭。局部變量每個字母都小寫單詞之間用下劃線連接。

ruby中一般只討論兩種作用域,全局作用域和局部作用域。全局變量在程序中任何地方都可以使用,覆蓋整個程序作用域。全局變量以$開頭。一般來說在程序中不使用全局變量。因爲全局變量會破壞對象的封裝性。但ruby解釋器啓動時會初始化很多全局變量。如$0 $:等。

在局部作用域中定義的局部變量只在該局部作用域中有效。在ruby中可以通過一下兩種規則來確定一個作用域:

頂層(在所有定義塊之外)有它自己的局部作用域

每個定義塊都會產生一個局部作用域,包括類定義塊、模塊定義塊以及方法定義塊,既是是嵌套的類和模塊定義塊也是一樣。

嚴格的來說出了上述兩條規則外還有其他的附加情況,但一般情況下很少碰到。

記住每次使用關鍵字def、class、module引入一個定義塊時,就開始了一個新的局部作用域,無論是否嵌套都是如此。

和局部變量類似,常量也遵循類似規則。

局部作用域與self

還有一條規則:ruby中代碼塊並不產生一個局部作用域

在頂層中,有一個上下文同時也是一個獨立的局部作用域。當開始一個定義塊(方法、類、模塊)時,就開始了一個新的局部作用域,同時也開始了一塊具有唯一一個特定的self的代碼。這看起來self與局部作用域規則幾乎是一樣的,似乎是一個概念。但其實不然,它們不僅不是同一事務同時也是不是同一種事務。由一個定義塊轉換到另一定義塊時可能上下文爲改變,self代表的還是同一個對象,而局部作用域卻肯定改變了。同時不進入一個新的作用域也有可能改變self。比如調用eval函數族insance_eval、class_eval等時局部作用域未改變但是可能改變self。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章