ruby instance_execメソッド

2022.08.04

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メソッドを使うようにする。