束縛
- ブロックを作成すると、xのようなローカル変数を包み込む
- メソッドにも束縛が存在する
- メソッドにあるxではなく、ブロックが定義された時のxを見ている
- メソッドにある束縛はブロックから見えない
def my_method x = 'メソッドの中' # !> assigned but unused variable - x yield('メソッドの中のブロック') end x = 'メソッドの外' my_method { |y| "#{x} #{y} どれが出力される?" } # => "メソッドの外 メソッドの中のブロック どれが出力される?"
- ブロックの中で新しい束縛を定義することもできる
- しかし、ブロックが終了した時点で消えてしまう
def just_yield yield end top_level_variable = 1 just_yield do top_level_variable += 1 # ブロックの中でローカル変数を定義する # でもブロックの中だけで、外から呼び出すとエラーになる local_to_block = 1 # 新しい束縛 # !> assigned but unused variable - local_to_block end top_level_variable # => 2 local_to_block # => Error
スコープ
クラス、メソッドがスコープになる
v1 = 1 local_variables # => [:v1] class MyClass v2 = 2 # !> assigned but unused variable - v2 local_variables # => [:v2] def my_method v3 = 3 # !> assigned but unused variable - v3 local_variables # => [:v3] end local_variables # => [:v2] end obj = MyClass.new obj.my_method # => [:v3] obj.my_method # => [:v3] local_variables # => [:v1, :obj]
グローバル変数はどのスコープからもアクセスできる
def a_scope $var = 'some value' end def another_scope $var end a_scope # => "some value" another_scope # => "some value"
- グローバル変数の代わりにトップレベルのインスタンス変数を使うこともできる
- selfになる場所であればどこからでも呼び出せる
@var = 'トップレベルの変数@var' def my_method @var end my_method # => "トップレベルの変数@var"
- 他のオブジェクトがselfになれば、トップレベルのインスタンス変数はスコープから外れる
@var = 'トップレベルの変数@var' def my_method # !> @var end my_method # => "トップレベルの変数@var" class MyClass def my_method # !> @var = 'トップレベルの変数@varではない' end end MyClass.new.my_method # => "トップレベルの変数@varではない"
スコープゲート
v1 = 1 class MyClass # スコープゲート: classの入口 v2 = 2 local_variables # => [:v2, :_xmp_1497065613_37095_295127] def my_method # スコープゲート: defの入口 v3 = 3 # local_variables end # スコープゲート defの出口 local_variables end # スコープゲート classの出口 obj = MyClass.new obj.my_method # => [:v3] local_variables # => [:v1, :obj, :_xmp_1497065613_37095_295127]
スコープゲートのフラット化
my_var = '成功' MyClass = Class.new do # これでmy_varを表示できる p "クラス定義の中は#{my_var}" define_method :my_method do "メソッド定義のなかも#{my_var}!" end end MyClass.new.my_method # => "メソッド定義のなかも成功!" # >> "クラス定義の中は成功"
スコープの共有
複数のメソッドで変数を共有したいが、その他からは見えないようにしたいときはフラットスコープを用いる
def define_methods shared = 0 Kernel.send :define_method, :counter do shared end Kernel.send :define_method, :inc do |x| shared += x end end define_methods # => :inc counter # => 0 inc(4) # => 4 counter # => 4
トップレベルのメソッド定義
- トップレベルにメソッドを定義すると,どのクラスからも呼び出せる
- 同名のローカル変数を作成した場合、ローカル変数が優先される
def foo p 'foo' end class MyClass foo end class MyClass foo = 'MyClass foo' p foo end class MyClass foo end class MyClass foo # => "foo" def bar self.foo end def foo 'MyClass foo method' end end MyClass.new.bar # => "MyClass foo method" # >> "foo" # >> "MyClass foo" # >> "foo" # >> "foo"
コメントを残す