ナスカブログ

未来の自分へのドキュメント

Ruby Goldへの道 day11

以下のサイトでruby gold取得に向けて毎日一回Goldチャレンジを行い間違えた問題を簡単にまとめる。 rex.libertyfish.co.jp

11日目 得点 64点/100点中

安定して70点を超えていたのに急に落ちた。 まだまだ理解が足りんな。

  • 定数の参照は静的に行われる。継承を辿っていかない
module M
  CONST = "Hello, world"
end

class M::C
  def awesome_method
    CONST
    # 定数の参照はレキシカルに行われる
    # 継承を辿っていかない
    # M::CONST #=> "Hello, world"
  end
end

p M::C.new.awesome_method
##=>  uninitialized constant M::C::CONST (NameError)
  • class_eval
    • ブロックを渡すとネストの状態はモジュールなのでモジュールの定数を参照
    • 文字列を渡すとネストの状態はクラスなのでクラスの定数を参照
class C
end

module M
  CONST = "Hello, world"

  C.class_eval do
    # ブロックを渡すのでモジュールMに
    def awesome_method
      # モジュールMのCONSTを参照する
      CONST
    end
  end
end

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

module M
  # 文字列を渡すのでネストの状態はクラスC
  # CクラスのCONSTを参照する
  C.class_eval(<<-CODE)
    def awesome_method
      CONST
    end
  CODE
end

p C.new.awesome_method
  • Module#refine
  • 引数で指定したクラスまたはモジュールに対してブロック内の機能を提供する
class C
  def m1
    200
  end
end

module R
  refine C do
    # Cクラスにm1メソッドを定義する
    # この場合m1メソッドをオーバーライドする
    def m1
      100
    end
  end
end

using R
# モジュールRを有効化する

c = C.new
puts c.m1 #=> 100