Ruby の変数と定数の種別は変数名の最初の一文字によって、
ローカル変数、
インスタンス変数、
クラス変数、
グローバル変数、
定数
のいずれかに区別されます。
通常の変数の二文字目以降は英数字または
_
ですが、組み込み変数の一部には
「`$
'+1文字の記号」という変数があります(組み込み変数を参照)。変数名
の長さにはメモリのサイズ以外の制限はありません。
例:
foobar
小文字または`_
'で始まる識別子はローカル変数また
はメソッド呼び出しです。ローカル変数スコープ(クラス、モジュー
ル、メソッド定義の本体)における小文字で始まる識別子への最初
の代入はそのスコープに属するローカル変数の宣言になります。宣
言されていない識別子の参照は引数の無いメソッド呼び出しとみな
されます。
ローカル変数のスコープは、宣言した位置からその変数が宣 言されたブロック、メソッド定義、またはクラス/モジュール定義 の終りまでです。寿命もそのブロックの終りまで(トップレベルの ローカル変数はプログラムの終了まで)ですが、例外としてブロッ クが手続きオブジェクト化された場合は、そのオブジェクトが消滅 するまで存在します。同じスコープを参照する手続きオブジェクト 間ではローカル変数は共有されます。
# (A) の部分はスコープに入らない 2.times { p defined?(v) # (A) v = 1 # ここ(宣言開始)から p v # ここ(ブロックの終り)までが v のスコープ } # => nil 1 nil <- これが nil であることに注意 1
宣言は、例え実行されなくても宣言とみなされます。
v = 1 if false # 代入は行われないが宣言は有効 p defined?(v) # => "local-variable" p v # => nil
またあまり推奨はされませんが -K オプションを指定 すれば日本語文字の識別子も使用でき、それはローカル変数とみなされます。
例:
@foobar
`@
'で始まる変数はインスタンス変数であり、特定の
オブジェクトに所属しています。インスタンス変数はそのクラスま
たはサブクラスのメソッドから参照できます。初期化されていない
インスタンス変数を参照した時の値はnil
です。
例:
class Foo @@foo = 1 def bar puts @@foo end end
@@
で始まる変数はクラス変数です。クラス変数はクラス定義
の中で定義され、クラスの特異メソッド、インスタンスメソッドなどから参照/
代入ができます。
クラス変数と定数の違いは以下の通りです。
クラス変数はクラス自身のインスタンス変数とは以下の点で異なります。
クラス変数は、そのクラスやサブクラス、それらのインスタンスで共有される グローバル変数であるとみなすことができます。
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 $/
`$
'で始まる変数はグローバル変数で、プログラムの
どこからでも参照できます(その分、利用には注意が必要です)。
グローバル変数には宣言は必要ありません。
初期化されていないグローバル変数を参照した時の値は
nil
です。
通常の変数以外に疑似変数と呼ばれる特殊な変数があります。
self
現在のメソッドの実行主体
nil
NilClassクラスの唯一のインスタンス
true
TrueClassクラスの唯一のインスタンス。真の代表値
false
FalseClassクラスの唯一のインスタンス。nilとfalseは偽を表します。
__FILE__
現在のソースファイル名 *1
__LINE__
現在のソースファイル中の行番号
疑似変数の値を変更することはできません。 擬似変数へ代入すると文法エラーになります。
例:
FOOBAR
アルファベット大文字 ([A-Z]
) で始まる識別子は定数です。
定数の定義 (と初期化) は代入によって行われますが、メソッドの
中では定義できません。一度定義された定数に再び代入を行おうと
すると警告メッセージが出ます。定義されていない定数にアクセス
すると例外 NameError が発生します。
定数はその定数が定義されたクラス/モジュール定義の中(メソッド 本体やネストしたクラス/モジュール定義中を含みます)、クラスを 継承しているクラス、モジュールをインクルードしているクラスま たはモジュールから参照することができます。クラス定義の外(トッ プレベル)で定義された定数は Object に所属することになり ます。
例:
class Foo FOO = 'FOO' # クラス Foo の定数 FOO を定義(Foo::FOO) end class Bar < Foo BAR = 'BAR' # クラス Bar の定数 BAR を定義(Bar::BAR) # 親クラスの定数は直接参照できる p FOO # => "FOO" class Baz # ネストしたクラスはクラスの継承関係上は無関係であるがネス # トの外側の定数も直接参照できる p BAR # => "BAR" end end
またクラス定義式はクラスオブジェクトの生 成を行うと同時に、名前がクラス名である定数にクラスオブジェクトを代入す る動作をします。クラス名を参照することは文法上は定数を参照していること になります。
class C end p C # => C
あるクラスまたはモジュールで定義された定数を外部から参照する
ためには`::
'演算子を用います。またObject
クラスで
定義されている定数(トップレベルの定数と言う)を確実に参照する
ためには左辺無しの`::
'演算子が使えます。
ただしこれらの `::
' 演算子を用いて定数に代入すること
はできません。
ruby 1.8 feature: `::
' 演算子を用いた定数への代入が可能に
なりました。
例:
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
親クラスとネストの外側のクラスで同名の定数が定義されているとネストの外 側の定数の方を先に参照します。つまり、定数参照時の定数の探索順序は、最 初にネスト関係を外側に向かって探索し、次に継承関係を上位に向かって探索 します。
例:
class Foo CONST = 'Foo' end class Bar CONST = 'Bar' class Baz < Foo p CONST # => "Bar" 外側の定数 # この場合、親クラスの定数は明示的に指定しなければ見えない p Foo::CONST # => "Foo" end end
トップレベルの定数定義はネストの外側とはみなされません。したがってトッ プレベルの定数は、継承関係を探索した結果で参照されるので優先順位は低い と言えます。
例:
class Foo CONST = 'Foo' end CONST = 'Object' class Bar < Foo p CONST # => "Foo" end # 以下のように明示的にネストしていれば規則通り Object の定数 # (ネストの外側)が先に探索される class Object class Bar < Foo p CONST # => "Object" end end
上位のクラス(クラスの継承関係上、およびネストの関係上の上位クラス)の定 数と同名の定数(下の例で CONST) に代入を行うと、上位の定数への代入では なく、そのクラスの定数の定義になります。
例:
class Foo CONST = 'Foo' end class Bar < Foo p CONST # => "Foo" CONST = 'Bar' # Bar の定数 CONST を*定義* p CONST # => "Bar" (Foo::CONST は隠蔽される) p Foo::CONST # => "Foo" (:: 演算子で明示すれば見える) end
*1 フルパスとは限らないため、フルパスが必要な場合は
File.expand_path(__FILE__)
とする必要があります。