?
This document uses PHP Chinese website manual Release
您可以通過(guò)區(qū)分Ruby變量名的首位字符來(lái)確定它是局部變量、實(shí)例變量、類變量、全局變量還是常數(shù)。通常情況下,變量名的第二位字符以后是數(shù)字、字母或下劃線,但有的內(nèi)部變量名比較特殊,如“'$'+1個(gè)符號(hào)”(請(qǐng)參考內(nèi)部變量)。變量名長(zhǎng)度只受內(nèi)存大小的限制。
例:
foobar
若標(biāo)識(shí)符首位是小寫字母或“_”,則該標(biāo)識(shí)符就是局部變量或方法調(diào)用。在局部變量的作用域(類、模塊、方法的定義部分)內(nèi),若對(duì)一個(gè)首位是小寫字母的標(biāo)識(shí)符進(jìn)行首次賦值的話,也就意味著聲明了一個(gè)屬于該作用域的局部變量。若引用尚未被聲明的標(biāo)識(shí)符的話,就會(huì)被解釋成一個(gè)無(wú)參數(shù)的方法調(diào)用。
局部變量的作用域起始于聲明處,結(jié)束于該聲明所在的塊、方法定義、類/模塊定義的結(jié)尾。隨著塊的消亡,局部變量也將壽終正寢(頂層局部變量則一直持續(xù)到程序終結(jié)),但也有例外。若塊已經(jīng)變成過(guò)程對(duì)象的話,則局部變量將一直持續(xù)到該過(guò)程對(duì)象終結(jié)為止。若多個(gè)過(guò)程對(duì)象引用同一個(gè)作用域的話,局部變量將被這些對(duì)象所共享。
# (A)的部分位于作用域之外 2.times { p defined?(v) # (A) v = 1 # 從(開始聲明)起 p v # 到(塊的終結(jié))是 v 的作用域 } # => nil 1 nil <- 請(qǐng)注意這里是 nil 1
即使聲明部分未被執(zhí)行仍將有效。
v = 1 if false # 雖未賦值,但聲明有效 p defined?(v) # => "local-variable" p v # => nil
若使用了 -K 選項(xiàng)的話就可以使用日語(yǔ)標(biāo)識(shí)符,日語(yǔ)標(biāo)識(shí)符被當(dāng)作局部變量處理。實(shí)際上,我們并不推薦您這樣做。
例:
@foobar
以@開始的變量是實(shí)例變量,它屬于特定的對(duì)象??梢栽陬惢蜃宇惖姆椒ㄖ幸脤?shí)例變量。若引用尚未被初始化的實(shí)例變量的話,其值為nil。
例:
class Foo @@foo = 1 def bar puts @@foo end end
以@@開始的變量是類變量。在類的定義中定義類變量,可以在類的特殊方法、實(shí)例方法等處對(duì)類變量進(jìn)行引用/賦值。
類變量與常數(shù)的區(qū)別如下。
類變量與類的實(shí)例變量的區(qū)別如下。
可以把類變量看作一種被類、子類以及它們的實(shí)例所共享的全局變量。
class Foo @@foo = 1 end class Bar < Foo p @@foo += 1 # => 2 end class Baz < Bar p @@foo += 1 # => 3 end
模塊中定義的類變量(模塊變量)被所有包含該模塊的類所共享。
module Foo @@foo = 1 end class Bar include Foo p @@foo += 1 # => 2 end class Baz include Foo p @@foo += 1 # => 3 end
例:
$foobar $/
以$開始的變量是全局變量,可以在程序的任何地方加以引用(因此需要特別留意)。全局變量無(wú)需變量聲明。引用尚未初始化的全局變量時(shí),其值為 nil。
除普通的變量之外,還有一種叫做偽變量的特殊變量。
self
當(dāng)前方法的執(zhí)行主體
nil
NilClass類的唯一實(shí)例
true
TrueClass類的唯一實(shí)例
false
FalseClass類的唯一實(shí)例。nil 和 false 表示“偽”。
__FILE__
當(dāng)前源文件名
__LINE__
當(dāng)前源文件中的行號(hào)
偽變量的值不可改變,若對(duì)偽變量賦值將引發(fā)語(yǔ)法錯(cuò)誤。
例:
FOOBAR
以大寫字母([A-Z])開始的標(biāo)識(shí)符是常數(shù).常數(shù)的定義(和初始化)由賦值過(guò)程完成.不能在方法中對(duì)常數(shù)進(jìn)行定義.若對(duì)已定義的常數(shù)進(jìn)行賦值的話,會(huì)出現(xiàn)警告信息.若引用未定義的常數(shù)的話,則會(huì)引發(fā)NameError異常.
可以在下列地方引用常數(shù),如,定義常數(shù)的類/模塊的定義句(也包括方法正文以及嵌套類/模塊的定義句)中,繼承該類的子類中,以及包含模塊的類/模塊中等等.在類定義之外(頂層)定義的常數(shù)屬于Object.
例:
class Foo FOO = 'FOO' # 定義Foo類的常數(shù)FOO(Foo::FOO) end class Bar < Foo BAR = 'BAR' # 定義Bar類的常數(shù)BAR(Bar::BAR) # 可直接引用父類的常數(shù) p FOO # => "FOO" class Baz # 雖然嵌套類與該類間不存在繼承關(guān)系 # 但還是可以直接引用嵌套外部的常數(shù) p BAR # => "BAR" end end
另外,在類定義表達(dá)式生成類對(duì)象的同時(shí),還會(huì)將類對(duì)象賦值給一個(gè)與該類同名的常數(shù).從語(yǔ)法上講,引用類名也就是引用該常數(shù).
class C end p C # => C
若想在外部訪問(wèn)類或模塊中的常數(shù)時(shí),要使用"::"操作符.若想準(zhǔn)確地訪問(wèn)Object類中的常數(shù)(頂層的常數(shù))時(shí),也需要也使用"::"操作符,但操作符左邊為空.另外,不能使用該操作符對(duì)常數(shù)進(jìn)行賦值.
ruby 1.8 特性: 可以使用"::"對(duì)常數(shù)進(jìn)行賦值.
例:
module M I = 35 class C end end p M::I #=> 35 p M::C #=> M::C p ::M #=> M M::NewConst = 777 # error--> parse error
若在父類和嵌套外側(cè)存在同名常數(shù)時(shí),會(huì)先引用嵌套外側(cè)的常數(shù).也就是說(shuō),引用常數(shù)時(shí)會(huì)先搜索嵌套關(guān)系的外側(cè),然后才會(huì)按照繼承關(guān)系向上搜索.
例:
class Foo CONST = 'Foo' end class Bar CONST = 'Bar' class Baz < Foo p CONST # => "Bar" 外側(cè)的常數(shù) # 此時(shí),若不顯式地指定父類中的常數(shù)的話,則無(wú)法找到該常數(shù) p Foo::CONST # => "Foo" end end
一般認(rèn)為頂層常數(shù)定義并不是位于嵌套外側(cè),所以在搜索了繼承關(guān)系之后才能找到它.可見(jiàn)頂層常數(shù)的優(yōu)先度很低.
例:
class Foo CONST = 'Foo' end CONST = 'Object' class Bar < Foo p CONST # => "Foo" end # 若能明顯看出是嵌套關(guān)系的話,按規(guī)則來(lái)說(shuō) # 首先搜索到的是Object的常數(shù)(位于嵌套外側(cè)) class Object class Bar < Foo p CONST # => "Object" end end
若對(duì)與父類常數(shù)同名的常數(shù)進(jìn)行賦值的話,則意味著在該類中定義一個(gè)新常數(shù),而并不會(huì)對(duì)父類常數(shù)進(jìn)行賦值.
例:
class Foo CONST = 'Foo' end class Bar < Foo p CONST # => "Foo" CONST = 'Bar' # *定義*Bar的常數(shù)CONST p CONST # => "Bar" (Foo::CONST 被屏蔽了) p Foo::CONST # => "Foo" (若使用:: 的話就可以了) end