classキーワードとclass_evalメソッド
Module.class_evalメソッドってどういうときに使うんだっけ、どうしてclassキーワードを使わないんだろと、ふと気になったので簡単にまとめておく。
classキーワード
- 定数(クラス名)を必要とする
- 現在の束縛を捨てて、新しいスコープをオープン
- classはスコープゲートとして振る舞う
class_eval (module_eval)
- クラスを参照する変数なら何でも使える、クラス名がわからなくてもよい
- フラットスコープを持つ
- class_evalブロックの外にあるスコープにある変数も参照することができる
そもそも、class_evalメソッドはレシーバをコンテキストとして文字列やブロックを評価するメソッド。
Fixnum.class_eval{ def number;self;end} 7.number #=> 7
ブロック同様、文字列も評価する。
Fixnum.class_eval "def number ; self ;end" 5.number #=> 5
evalメソッド同様、privateメソッドの呼び出しも可能なので、使用する際には注意が必要。
Rubyリファレンスを見てみると、次のような記述がある。
class_evalメソッドは、ブロックをクラス定義やモジュール定義の中のコードであるように実行します。ブロックの戻り値がメソッドの戻り値になります。
module_evalメソッドはclass_evalの別名です。Classオブジェクトに対してmodule_evalを呼び出せますし、Moduleオブジェクトに対してclass_evalを呼び出せます。
ブロック内でのselfはClassオブジェクトやModuleオブジェクトを指します。ブロックの外側のローカル変数はブロック内でも使えます。
class_eval、module_evalを使うと、クラスやモジュールの外側でインスタンスメソッドを定義したり、Moduleクラスのprivateメソッドを呼び出したりできます。
なるほど。