class_evalのスコープの違いについて

Module#class_evalの引数

Module#class_evalには、引数に文字列またはブロックを受け取ります。

class_eval(expr, fname = "(eval)", lineno = 1) -> object
class_eval {|mod| ... } -> object

引数が文字列の時とブロックの時では、スコープが異なります。

文字列が与えられた場合には、定数とクラス変数のスコープは自身のモジュール定義式内と同じスコープになります。
ブロックが与えられた場合には、定数とクラス変数のスコープはブロックの外側のスコープになります。

instance method Module#class_eval (Ruby 2.5.0)』より

引数が文字列とブロックでは、スコープはどのように違うのでしょうか。
動作の違いを確認しました。

引数が文字列の時のスコープ

文字列が与えられた場合には、定数とクラス変数のスコープは自身のモジュール定義式内と同じスコープになります。

引数が文字列の場合は、クラスCの定数XXXにアクセスできるため、次のコードは動作しました。

class C
    XXX = 'XXX'
end

C.class_eval(<<-CODE)
    def foo
        XXX
    end
CODE

p C.new.foo

引数がブロックの時のスコープ

引数がブロックの場合は、クラスCの定数XXXにアクセスできないため、次のコードはエラーになりました。

class C
    XXX = 'XXX'
end

C.class_eval do
    def foo
        XXX
    end
end

p C.new.foo

コメントを残す

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

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください