LoginSignup
6
0

More than 5 years have passed since last update.

Rubyでクラスの継承チェーンをのぞいて見る

Posted at

Rubyで普段から使ってるStringクラスとか、どういったクラスを継承しているのか気になったため、調べたことをまとめておきます。

継承チェーンとは?
Rubyのクラスのスーパークラスを見る、そのスーパークラスのスーパークラスを見る、をBasicObjectが見つかるまで続ける。
このクラスの道筋が継承チェーンとなります。
Stringクラスの場合だと以下のようになります。
irbで確認してみましょう

# Stringのスーパークラスを確認
irb(main):001:0> String.superclass
=> Object

# StringのスーパークラスであるObjectのスーパークラスを確認
irb(main):002:0> Object.superclass
=> BasicObject

StringクラスのスーパークラスがObjectクラス、ObjectクラスのスーパークラスがBasicObjectクラスとなっています。
ちなみにBasicObjectクラスを見ると

irb(main):003:0> BasicObject.superclass
=> nil

となっているので、BasicObjectクラスが終点であることがわかります。

継承チェーンのモジュールについて
しかしここでクラスの親クラスを返すancestorsメソッドを使用して見ると

irb(main):004:0> String.ancestors
=> [String, Comparable, Object, Kernel, BasicObject]

先ほどスーパークラスで辿った時に出てこなかった「Comparable」と「Kernel」が出てきましたね。
これらは、クラスではなくモジュールとなります。
モジュールはクラスにインクルードされることで、クラスの継承チェーンに挿入されます。
KernelはObjectクラスにインクルードされています。
https://docs.ruby-lang.org/ja/latest/class/Kernel.html

ComparableはStringにインクルードされています。
https://docs.ruby-lang.org/ja/latest/class/String.html

このようにString一つとっても複数のクラスとモジュールが継承されていることがわかります。

次にインクルードをする場合、継承チェーンのどこに挿入されるのでしょうか?
またインクルードする順番は関係するのでしょうか?
試してみましょう。
以下のコードを動かしてみます。

module A
end

module B
end

class C
  include A
  include B
end

p C.ancestors

実行結果は

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

まず自作クラスのスーパークラスはデフォルトでObjectクラスになるのですが、
インクルードされたModuleがスーパークラスの前に差し込まれています。
またBの方がAより先に来ています、
つまりインクルードすると、
・自分のクラスの後に差し込まれる
・複数インクルードすると後に指定した方が継承チェーンでは先に来る
となります。

ちなみに

module A
end

module B
end

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

p C.ancestors

とincludeをprependに変更すると、自分のクラスの後ではなく先に挿入されます。
以下実行結果です

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

Cより先にAが来ていますね。

このように継承チェーンのどこに差し込むかは、includeを使うかprependを使うか、
includeの場合は、上に書くか下に書くかで変わって来ます。

参考文献
メタプログラミングRuby 第2版

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