紳士なブログ

紳士すぎてすみません

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メソッドを呼び出したりできます。


なるほど。