LoginSignup
6
1

More than 5 years have passed since last update.

RubyでModuleをレシーバとしたinstance_evalとmodule_eval

Last updated at Posted at 2019-03-18

C#erがRubyのModuleについてのinstance_evalとmodule_evalを理解するのにハマった点をまとめておく。

サンプルに使用するモジュールの定義

module M
  CONST = "Module CONST"
  class << self
      CONST = "Module Singleton CONST"
  end
end

文字列を使用してinstance_evalする場合

モジュールの特異メソッドが定義される
モジュールの特異クラス内で評価

M.instance_eval(<<-CODE)
  def say
    p CONST
  end
CODE

M.say # => "Module Singleton CONST"

関数の定義はdef sayでもdef self.sayでも直接呼び出せる。
今の理解度では、def self.sayがOKな理由がわからない。
def self.sayは、特異クラスの特異クラスに定義されそうな気がするのだが。。。

文字列を使用してmodule_evalする場合

モジュールのインスタンスメソッドが定義される
モジュール内で評価

M.module_eval(<<-CODE)
  def self.say
    p CONST
  end
CODE

M.say # => "Module CONST"

関数の定義はdef self.sayでなければ直接呼び出せない。

コードでinstance_evalする場合

モジュールの特異メソッドが定義される
カレント(この場合はトップレベル)で評価

CONST = 'TOP LEVEL'
M.instance_eval{
  def say
    p CONST
  end
}

M.say # => "TOP LEVEL"

関数の定義はdef sayでもdef self.sayでも直接呼び出せる。
今の理解度では、def self.sayがOKな理由がわからない。

コードでmodule_evalする場合

モジュールのインスタンスメソッドが定義される
カレント(この場合はトップレベル)で評価

CONST = 'TOP LEVEL'
M.module_eval{
  def self.say
    p CONST
  end
}

M.say # => "TOP LEVEL"

関数の定義はdef self.sayでなければ直接呼び出せない。

class << Module を使用する場合

モジュールの特異メソッドが定義される
モジュールの特異クラス内で評価

class << M
  def say
    p CONST
  end
end

M.say # => "Module Singleton CONST"

関数の定義はdef sayでなければ直接呼び出せない。
文字列を使用してinstance_evalする場合と似ているが、def self.sayは直接呼び出せない。

深すぎるよ。。。

6
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1