class_execとは
与えられたブロックを指定された args を引数としてモジュールのコンテキストで評価します。モジュールのコンテキストで評価するとは、実行中そのモジュールが self になるということです。つまり、そのモジュールの定義式の中にあるかのように実行されます。ローカル変数、定数とクラス変数のスコープはブロックの外側のスコープになります。
Ruby3.1 リファレンス
class_evalとほとんど同じ扱いになる。class_evalについて
違いは引数でブロックを呼び出せるかということになる。
特徴
クラスインスタンス変数を定義できる。インスタンス変数ではないことに注意。クラスインスタンス変数について
class Hoge
@x = 3
def initialize
@y = 2
end
end
p Hoge.instance_variables #=> [:@x]
Hoge.class_exec{@x = 5}
Hoge.class_exec{@y = 22}
p Hoge.instance_variable_get(:@x) #=> 5
p Hoge.instance_variable_get(:@y) #=> 22
h = Hoge.new
p Hoge.instance_variables #=> [:@x, :@y]
p h.instance_variables #=> [:@y] オブジェクトhにはインスタンス変数は@yのみ
p h.instance_variable_get(:@x) #=> nil
p h.instance_variable_get(:@y) #=> 2
クラスの外側で定義した変数を扱える
# 通常は呼び出せない
x = 1
class Hoge
@x = x
end
p Hoge.instance_variables
#=> undefined local variable or method `x' for Hoge:Class (NameError)
#Aクラスのインスタンス変数として呼び出せる
x = 1
class Hoge
end
Hoge.class_exec do
@x = x
end
p Hoge.instance_variables
#=> [:@x]
プライベートメソッドが呼び出せないのもclass_evalと同じだ。
class Hoge
@z = 3
def initialize
@y = 2
end
private
def p_m
'プライベート'
end
end
p Hoge.class_exec{p_m} #=> undefined local variable or method `p_m' for Hoge:Class (NameError)
インスタンスメソッドを設定できる。
class Hoge
end
Hoge.class_exec do
def a
"a"
end
end
h = Hoge.new
p h.a
class_evalとの違い
引数でブロックを呼び出せる。
class Hoge
end
a = lambda{p "hello"}
h = Hoge.new
p Hoge.class_exec(&a) #=> "hello"
class_evalは引数でブロックを呼び出せない。
class Hoge
end
a = lambda{"hello"}
h = Hoge.new
p Hoge.class_eval(&a) #=> wrong number of arguments (given 1, expected 0) (ArgumentError)
instance_execとの違い
instance_evalとclass_evalの違いと同じです。
instance_exec ・・特異メソッドを作成。インスタンス変数を設定。プライベートメソッドにアクセス可能。引数にブロックを使える。
class_exec・・インスタンスメソッドを作成。クラスインスタンス変数を設定。プライベートメソッドにアクセス不可。引数にブロック使える。
まとめ
instance_execと同じく引数でブロックを呼び出し可能だと分かった。それ以外はclass_evalと同じ処理になる。
class_execは引数でブロックを呼び出したい処理で使用できることを考えると若干class_evalよりも上位な位置にあると思いました。