オブジェクトの継承関係を把握しよう!(Ruby)
Rubyを勉強している時にこう思ったことはないですか。「オブジェクト指向って何」。「putsやto_sメソッドは定義していないのにどこからやってきたんだ」というか何でデフォルトでこんなにメソッドを使えるのかと。今回はそんなもどかしい気持ちを解決するために「メタプログラミングRuby第2版」という本を買ってきました。その備忘録として書きます。
1 オブジェクトとは
「Ruby で扱える全ての値はオブジェクトです。」Rubyを勉強している人なら皆知っていると思いますが、今回は改めて、全てがobjectになっているのかどうか実行して調べたいと思います。
まずはインスタンスを確認
.classはレシーバがどのクラスのインスタンスか調べるメソッドです。(ここではobjを調べている)実行結果からobjはAクラスのインスタンスであることがわかりますね。
では次にAクラスのクラスを調べてみましょう。
AクラスはClassクラスのインスタンスであることがわかりました。では最後にClassクラスのクラスを調べましょう(ややこしい)
結果はClassでした。ここからわかることはClassクラス自信がclassを生成しているということですね。
2継承クラスを調べる
先程まではオブジェクトのクラスを調べていましたが、今度は継承クラスを調べます。「何が違うねん」とツッコミをいれられそうなので僕なりに簡単に説明すると、クラスは横の繋がり、継承クラスは縦の繋がりを表しています。
先程の横の繋がり
次はこの矢印が上方向のクラスを調べます。
さっきと同じようにインスタンスから調べてみましょう。
.superクラスはレシーバのクラスの親クラスを調べるメソッドですがErrorが起こっていますね。どうやらobjはインスタンスであるためこのメソッドは使えないようです。
次にAクラスの親クラスをを調べてみます。
Aクラスの親クラスはObjectクラスのようです、遂にオブジェクト指向の本質がみえてきましたね。
次はClassクラスの親クラスを調べてみましょう。
結果はModuleでした。こうなると気になるのはModuleの親クラスですね。調べてみます。
またObjectに戻ってきました。ここまでの結果を図にして書いてみます!
つまり、僕たちが自分で定義したメソッドやインスタンスは全てObjectクラスを引き継いでいることが分かりました。これがオブジェクト指向と言われる理由ですね。
もう一つの疑問である「puts」や「to_s」等のメソッドはどこに定義されているのかを調べるために「 ancestors」メソッド使います。このメソッドはレシーバの親クラスを遡って調べ、配列にして返してくれるメソッドです。ちなみに親クラスの他にインクルードされているModuleも含んで遡ります。では、Objectクラスに「ancestors」を使い調べてみます。
継承にKernelというModuleが入っています。怪しいので「methods」メソッド(レシーバが持っているメソッドを配列で返す)を使いKernelに定義されているメソッドを調べてみます。
ものすごい数のメソッドが出てきました... この中に「puts」メソッドだけでなく「Array」や「String」など、普段使っているクラスが定義されていますね。
まとめると、ObjectはKernelモジュールを継承しているため、僕たちが定義したクラスやインスタンスはKernelを引き継いでいる、そのためデフォルトで「Array」や「String」などのメソッドを使うことができるというわけですね!
RubyのフレームワークであるRailsも継承を使う場面が非常に多いので、こういった継承関係を常に意識して開発をしたいです!