Ruby Gold勉強メモ(2)

f:id:ihatov08:20160414004338j:plain

束縛

  • ブロックを作成すると、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"

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です