ようへいの日々精進XP

よかろうもん

2018 年 01 月 31 日(水)

ジョギング

  • 香椎浜 x 2 周
  • 風が殆ど無くて走りやすかった

日課

  • (腕立て x 50 + 腹筋 x 30) x 3

夕飯

  • パスタを作る
  • トメイトは湯むきしてソースを作り, 魚介はトメイトと一緒に煮込んだからかは分からないけど, 美味しく出来た気がする

今日のるびぃ ~ いつまでも覚えられないメソッド探索 ~

以下のようなコードがあった場合に, C2 をインスタンス化して to_s メソッドを呼んだ場合にどのような結果になるのか.

module A
  def to_s
    "<A> #{super}"
  end
end

module B
  def to_s
    "<B> #{super}"
  end
end

class C1
  def to_s
    "<C1> #{super}"
  end
end

class C2 < C1
  include A
  include B

  def to_s
    "<C2> #{super}"
  end
end

※ このコードは, プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで の「 第8章 モジュールを理解する」を参考にさせて頂きました. 有難う御座います.

まずは C2 クラスの継承関係を確認してみる.

[8] pry(main)> C2.ancestors
=> [C2, B, A, C1, Object, PP::ObjectMixin, Kernel, BasicObject]

C2 をインスタンス化して to_s メソッドを呼び出してみる.

[9] pry(main)> c = C2.new
=> #<C2:0x005559027a6c18>
[10] pry(main)> c.to_s
=> "<C2> <B> <A> <C1> #<C2:0x005559027a6c18>"
[11] pry(main)> C1.superclass
=> Object

なるほど. 以下のように呼ばれていることが解る.

  1. C2 クラスの to_s メソッド
  2. B モジュールの to_s メソッド
  3. A モジュールの to_s メソッド
  4. C2 クラスのスーパークラスである C1 クラスの to_s メソッド
  5. C1 クラスのスーパークラスである Object クラスである to_s メソッド

今更だけど, 2, 3, 4 あたりの順番が有耶無耶になっていた...(汗

ちなみに, 以下のようなクラスを追加した場合にはどのような探索経路になるのか.

class C3 < C1
  def to_s
    "<C3> #{super}"
  end
  
  include A
  include B
end

以下のように C2 クラスと同じ探索経路になった.

[13] pry(main)> C3.ancestors
=> [C3, B, A, C1, Object, PP::ObjectMixin, Kernel, BasicObject]

include ではなく prepend でモジュールを mix-in した場合にどうなるのか.

class C4 < C1
  prepend A
  prepend B

  def to_s
    "<C4> #{super}"
  end
end

以下のように B モジュールの to_s クラスが最初に呼ばれる.

[15] pry(main)> C4.ancestors
=> [B, A, C4, C1, Object, PP::ObjectMixin, Kernel, BasicObject]
[16] pry(main)> C4.new.to_s
=> "<B> <A> <C4> <C1> #<C4:0x00555902997ef0>"

ふむふむ. なんかスッキリした.