最も有用なevalファミリーメソッド:class_eval

1487 ワード

本質的にはclasseval(module_eval)は、クラス定義体に入ります.
1 c=Class.new
2 c.class_eval do
3    def some_method
4        puts "created in class_eval"
5    end
6 end
7 C.new.some_method   => "created in class_eval"

でも、class_evalはclassキーワードではできないことをします.
1.クラス定義のコンテキストで文字列を評価します.2.単一のクラスを含まない匿名クラスのクラス定義を開きます.3.周辺の役割ドメインの変数へのアクセス権を取得します.特に3つ目は、次のコードに注意してください.
1 var = "init var"
2 class C
3 puts var
4 end    => NameError:undefined local variable or method 'var' for C:Class..
5 
6 C.class_eval {puts var}
7        => init var 

変数varは、標準的なクラス定義体の役割ドメインの外にありますが、class_に渡されます.evalのコードブロックの役割ドメイン内.class_でevalのブロックでインスタンスメソッドを定義する場合は、次のように異なります.
1 C.class_eval{ def talk; puts var; end }
2 
3 C.new.talk  => undefined loc.'var'..

任意のdefと同様に、コードブロック内のdefは新しい役割ドメインを開くので、変数varはアクセスできません.
外部作用ドメインの変数をインスタンスメソッドにハードプラグする場合は、別の技術を使用してメソッドを生成できます:define_メソッド.
インスタンスメソッドで変数varにアクセスするには、次のようにします.
1 C.class_eval { define_method("talk"){puts var}}
2 C.new.talk
3     => init

このような技術者は,標準的なクラスやメソッド定義のように頻繁に使用されないが,それらを見たとき,平坦化された局所変数の役割ドメインを示唆していることが分かった.より一般的なclassやdefのように新しい役割ドメインを開くのではなく、
define_MethodはModuleクラスのインスタンスメソッドであるため、ModuleまたはClassの任意のインスタンスがこのメソッドを呼び出すことができます.インスタンスメソッドで通常のクラス定義体(このコンテキストでselfはクラスオブジェクト)のローカル変数にアクセスする場合は、通常のクラス定義体でdefine_を使用します.method.