instance_eval
レシーバとなるインスタンスのコンテキスト(特異クラス)でブロック(文字列)の処理を評価する。
レシーバをselfとして評価するので、privateメソッドやインスタンス変数にもアクセス可能。
class C
def initialize
@hoge = 'hoge'
end
end
c = C.new
c.instance_eval do
p self
# => #<C:0x00007f9fe61fda78 @hoge="hoge">
def hoge
@hoge
end
end
c.hoge
=> "hoge"
引数がブロックか文字列かで定数やローカル変数のスコープが変わる。
top = 'トップレベルのローカル変数だよ'
class C
c_top = 'Cのローカル変数だよ'
end
c = C.new
# ブロックの場合スコープはinstance_evalの外側になる。この場合トップレベル
c.instance_eval do
p Module.nesting # ネストの状態はトップレベル
# => []
p top
# => "トップレベルのローカル変数だよ"
p c_top # クラスCはスコープ外
# => NameError
end
# 特異メソッド定義
def c.hoge
p 'cの特異メソッドだよ'
end
# 文字列の場合スコープは特異クラスにいる
c.instance_eval <<-eval
p Module.nesting # ネストの状態は特異クラスにいる
# => [# <Class:# <C:0x00007f9fe61fda78>> ]
p c_top # 特異クラス内のため、クラスCはスコープ外
# => NameError
hoge # 特異メソッドを呼び出せる
# => "cの特異メソッドだよ"
eval
class_eval(module_eval)
クラスのコンテキストでブロック(文字列)を評価する。インスタンスメソッドやクラスメソッドを定義したりできる。
module_evalはclass_evalの別名。
class C; end
C.class_eval do
def self.call_method
p 'クラスメソッドだよ'
end
end
C.call_method
=> "クラスメソッドだよ"
引数がブロックか文字列かで定数やクラス変数のスコープが変わる。
TOPCONST = 'トップレベルの定数だよ'
class C
CCONST = 'Cの定数だよ'
end
# ブロックの場合スコープはclass_evalの外側になる。この場合トップレベル
C.class_eval do
p Module.nesting # ネストの状態はトップレベル
# => []
p TOPCONST
# => "トップレベルの定数だよ"
p CCONST # クラスCはスコープ外
# => NameError
end
# 文字列の場合スコープはclass_evalで評価したclass
C.class_eval <<-eval
p Module.nesting # ネストの状態はクラスC
# => [C]
p CCONST
# => "Cの定数だよ"
eval
eval
受け取った文字列をRubyコードとして実行する
eval('def huga; p 1 end')
huga
=> 1
0 件のコメント:
コメントを投稿