ナスカブログ

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

Ruby Goldへの道 day12

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

12日目 得点 68点/100点中

  • { }はdo..endより結合度が高いため実行結果に差が出る。
def m1(*)
  str = yield if block_given?
  p "m1 #{str}"
end

def m2(*)
  str = yield if block_given?
  p "m2 #{str}"
end

m1 m2 do
  "hello"
end
#=> "m2 "
#=> "m1 hello"

m1 m2 {
  "hello"
}
#=> "m2 hello"
#=> "m1 "
  • class内でusing モジュールを使用してもエラーにならない
  • スコープ外は無効になる
class C
  def m1
    400
  end
end

module M
  refine C do
    def m1
      100
    end
  end
end

class C
  using M
  # Mモジュール有効化
end
# スコープ外なのでMモジュールは無効

puts C.new.m1 #=> 400
  • モジュールをincludeしたら今いるクラスの真上に入る
  • メソッド探索は今いるクラスになかったらincludeしたモジュールに探索にいく
module M
  def method_missing(id, *args)
    puts "M#method_missing"
  end
end
class A
  include M
  def method_missing(id, *args) # これをコメントアウトするとMモジュールの#method_missingが呼ばれる 
    puts "A#method_missing"
  end
end
class B < A
  class << self
    def method_missing(id, *args)
      puts "B.method_missing"
    end
  end
end

B.new.dummy_method #=> A#method_missing
  • Refinementで再定義したメソッドの探索は優先的に行われる
  • usingの後でクラスを再オープンしてもrefineが先に探索される
class C
  def m1
    200
  end
end

module R
  refine C do
    def m1
      300
    end
  end
end

using R
# Rモジュール有効化

class C # クラス再オープン
  def m1
    100
  end
end

puts C.new.m1 #=> 300
# Refinementで再定義したメソッドが優先的に探索される