instance_execとは
与えられたブロックをレシーバのコンテキストで実行します。ブロック実行中は、 self がレシーバのコンテキストになるのでレシーバの持つインスタンス変数にアクセスすることができます。
Ruby3.1 リファレンス
特異メソッドやインスタンス変数の設定もできます。
instance_evalメソッドとの違いはブロックを引数付きで呼び出せるかという違いのみ。
特徴
インスタンス変数の設定、書き換えができる。他のオブジェクトには影響がない。
class Hoge
def initialize
@num = 1
end
end
h = Hoge.new
h2 = Hoge.new
p h.instance_variable_get(:@num) #=> 1
h.instance_exec{p @num} #=> 1
h.instance_exec{@num = 2}
h.instance_exec{@greeting = "hello"}
h.instance_exec{p @num} #=> 2
h.instance_exec{p @greeting} #=> "hello"
h2.instance_exec{p @num} #=> 1
特異メソッドを定義できる。他のオブジェクトには影響しない。
class Hoge
end
h = Hoge.new
h2 = Hoge.new
h.instance_exec do
def a
p "a"
end
end
h.a #=> "a"
h2.a #=> undefined method `a' for #<Hoge:0x00007f7c7095f008> (NoMethodError)
プライベートメソッドも呼び出し可能
class Hoge
private
def a_p
"プライベート"
end
end
h = Hoge.new
p h.instance_exec{a_p} #=> "プライベート"
instance_evalとの違い
ブロックを引数付きで呼べる
class Hoge
end
a = lambda{|name| name}
h = Hoge.new
p h.instance_exec("hello", &a) #=> "hello"
instance_evalはブロックを引数付きでは呼べない。
class Hoge
end
a = lambda{|name| name}
h = Hoge.new
p h.instance_eval("hello", &a) #=> wrong number of arguments (given 1, expected 0) (ArgumentError)
まとめ
ブロックを引数付きで呼び出せること以外はinstance_evalメソッドと同じと理解。
instance_execメソッドの方ができることが多い気がしている。ブロックを呼び出したい場合はinstance_execメソッドを使うようにする。