2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Ruby】class_evalで何が渡されたかによってネストの状態が変わるのややこしや〜

Last updated at Posted at 2024-12-30

どうもこんにちは。

今回も完全なるメモ書きです。温かい目で見守ってください。

定数の探索

module M
  CONST = "Hello, world"

  class C
    def awesome_method
      CONST    # レキシカルスコープ内で`CONST`が定義されているので、参照ができる
    end
  end
end

p M::C.new.awesome_method
module M
  CONST = "Hello, world"
end

class M::C
  # ここに`CONST`が定義されていれば参照可能
  def awesome_method
    CONST     # レキシカルスコープ内に`CONST`が定義されていないので、参照ができない
  end
end

p M::C.new.awesome_method

定数の探索は基本的にレキシカルスコープで行われますが、レキシカルスコープ内に定数が見つからなかった場合には、継承元クラスへ定数の探索を行います。

さぁ、ここからclass_eval出てきます!

class C
end

module M
  CONST = "Hello, world"

  C.class_eval do        # `class_eval`にはブロックが渡されています。この時のブロック内のネストの状態はモジュールMになります。
    def awesome_method
      CONST              # ネストの状態はモジュールMであり、レキシカルスコープ内にCONSTも存在しているので、参照が可能
    end
  end
end

p C.new.awesome_method
class C
  CONST = "Hello, world"
end

module M
  C.class_eval(<<-CODE)    # `class_eval`にはヒアドキュメントが渡されています。この時のネストの状態はクラスCです。
    def awesome_method
      CONST                # ネストの状態がクラスCである、クラスCに`CONST`が定義されているので、CONSTの参照が可能
    end
  CODE
end

p C.new.awesome_method
class C
  CONST = "Hello, world"
end

module M
  C.class_eval do        # `class_eval`にはブロックが渡されています。この時のブロック内のネストの状態はモジュールMになります。
    def awesome_method
      CONST              # ネストの状態はモジュールMですが、レキシカルスコープ内に`CONST`が存在していないので参照が不可能
    end
  end
end

p C.new.awesome_method
2
0
0

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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?