Rubyの変数と定数についてです。変数については慣れてくると意識しなくても使い分け出来るようになるんですが、最初は思わぬところで落とし穴にはまってたりして悩む事がよくありますよね。
ローカル変数
先頭がアルファベットの小文字か_で始まり、数字で始めると例外が発生します。また、最初に値が代入されたときに初期化されるため、初期化されていないローカル変数を参照した場合は、引数のないメソッドの呼び出しとみなされて例外が発生します。
name = "Ruby" # OK _name = "Ruby" # OK 1name = "Ruby" # エラー name # 事前に代入してない場合エラー
ローカル変数は同じスコープ内でのみ使用できる変数で、別のスコープで同じ名前の変数を使ったとしても別のローカル変数として扱われるため、次のように別メソッドで同じ名前の変数に値を代入した場合でも影響されません。
class Local def hoge name = "Ruby" # hogeメソッド内のローカル変数 fuga # fugaメソッド実行 p name # nameを表示 end def fuga name = "Java" # fugaメソッド内のローカル変数 end end local = Local.new local.hoge #=>"Ruby"
グローバル変数
先頭が「$」で始まります。「$」のあとに数字を付けることは出来ません。また、ローカル変数と違い初期化されていないグローバル変数を参照した場合でも例外は発生しませんが、nilが返ります。
$name1 # OK $1name # エラー
グローバル変数はプログラム中のどこで使われても同じ名前であれば、同じ変数として扱われます。一見便利そうですがあまり使う機会はなさそうです。どこからも参照できて変更もできるとなると色々と問題もありますから。Javaでいうとfinalのないstatic変数ですね。
インスタンス変数
「@」で始まる変数をインスタンス変数といいます。「@」のあとに数字を付けることはできません。初期化してないインスタンス変数を参照するとnilが返ります。
ローカル変数はメソッドごとに異なる変数として扱われますが、インスタンス変数は、同じインスタンス内であればメソッド定義を超えて、その値を参照したり変更したりできます。また、クラスの外部から直接アクセスすることはできません。
class Programing def name=(value) @name = value end def name @name end end hoge = Programing.new # インスタンス1生成 fuga = Programing.new # インスタンス2生成 hoge.name = "Ruby" # インスタンス1の変数にセット fuga.name = "Java" # インスタンス2の変数にセット hoge.name #=>"Ruby" fuga.name #=>"Java"
インスタンス変数の詳細は 【Ruby】インスタンス変数について も参照
クラス変数
「@@」で始まる変数をクラス変数といいます。「@@」のあとに数字を付けることはできません。初期化してないインスタンス変数を参照するとnilが返ります。
クラス変数はそのクラスのすべてのインスタンスで共有できる変数です。グローバル変数と似てますが、同じクラス内でのみになります。クラスの外部から直接アクセスすることはできません。これも使いどころが難しいですね。
class Programing @@name def name=(value) @@name = value end def output p @@name end end hoge = Programing.new # インスタンス1生成 fuga = Programing.new # インスタンス2生成 hoge.name = "Ruby" # インスタンス1の変数にセット fuga.name = "Java" # インスタンス2の変数にセット hoge.name #=> "Java" fuga.name #=> "Java"
擬似変数
これはRubyに予約された変数ですので、値を代入しようとするとエラーになります。よく出てくる nil や false , true などが擬似変数にあたります。
定数
定数はアルファベットの大文字で始まります。ただし、慣習として識別子はすべて大文字で、単語の区切りを「_」とします。
クラスで定義できますが、メソッドの中では定義できません。値が代入されることによって初期化・定義されるため、定義されていない定数にアクセスすると例外が発生します。また、定義されている定数に値を代入しようとすると警告があります。
class Foo Homepage = "google" def bar Site = "yahoo" #=> SyntaxError: (irb):64: dynamic constant assignment end end
定数にアクセスするには内部からはそのまま定数名でアクセスできますが、外部のクラスからの場合は::
演算子を用いて次のように参照します。ドット.
で参照するとメソッド参照と解釈されてNoMethodError
が発生します。
Foo::Homepage #=> "google" Foo.Homepage #=> NoMethodError: undefined method `Homepage' for Foo:Class
定数の詳細は 【Ruby】定数について も参照