バンビのブログ

駆け出しのエンジニアです!日々の疑問など備忘録として書いていきます。

継承チェーン

継承チェーンとは、そのオブジェクトがなんのオブジェクトを継承しているかのこと。

Rubyではオブジェクトの大元はBasicObjectというオブジェクトです。継承しているオブジェクトをたどっていくと行き着く先はBasicObjectになります。 その過程で継承しているクラスが様々なメソッドをもっていて、それらを僕たちが使っているというイメージです。

  1. スーパークラスのたどり方 superclassメソッドでスーパークラスを確認できる。
コンソールでirbをつかって確認

# Stringのスーパークラスを確認
String.superclass => Object

# StringのスーパークラスであるObjectのスーパークラスを確認
Object.superclass => BasicObject

# BasicObjectのスーパークラスを確認するがnilとなるのでここが大元となる
BasicObject.superclass => nil

これでスーパークラスが何かをたどることができました。 あのメソッドを使いたいが、どのクラスがもっていたかや、このクラスにあるはずのメソッドが使えないときに、継承もとをたどるとミスや勘違いを発見することができるかもです。

2.継承チェーン上のモジュールについて ancestorsメソッドを使うと親クラスすべてが確認できます。

 String.ancestors => [String, Comparable, Object, Kernel, BasicObject]

「Comparable」と「Kernel」はさっきのsuperclassにはなかったが、この2つはモジュールです。

・ KernelはObjectクラスにインクルードされていて、ComparableはStringにインクルードされています
  1. モジュールとクラスの読み込みのタイミング
module A
end

module B
end

# クラスC に モジュールAとBをincludeする
class C
  include A
  include B
end

p C.ancestors

[C, B, A, Object, Kernel, BasicObject]

というように、クラスCが読み込まれたあとに、モジュールを下から順に読み込んでいます。
なので、モジュールBがモジュールAのメソッドを使おうとすると読み込む順番的に method_missing が発生します。


# prependメソッドを使用すると読み込む順番が変わる

module A
end

module B
end

class C
  prepend A       #includeをprependに変更
  include B
end

p C.ancestors

[A, C, B, Object, Kernel, BasicObject]
となり、クラスよりも先にモジュールAが読み込まれる順に変わりました。

先に予め読み込ませて置くのを『preload』ともいうので覚えておくといいかも!!