Rubyのクラスについて(1)クラス定義
最近、メタプログラミングRubyやRubyの仕組みを読んでクラスについて勉強しているので、備忘録がてら内容をまとめておきます。
Rubyのクラス定義の方法
それではまず最初にRubyにおけるクラスについて書いていきます。Rubyでのクラス定義の方法は下記にようになります。
class A def hoge puts 'hoge' end end
このように定義して、newするとインスタンスができます。
pry(main)> a = A.new pry(main)> a.hoge hoge
何言ってんだと思われると思いますが、じゃあクラス定義とは実際、何を行なっているのでしょうか?
それを見ていきたいと思います。
クラス定義のやっていること
それではRubyはクラス定義で何をやっているのでしょうか?
実はRubyのクラス定義のやっていることは、Classクラスのインスタンスを生成し、定数に代入するということをやっています。
どういうことか説明していきます。まずclassクラスのインスタンスであることについて。
Rubyでは全てがオブジェクトになります。クラスも例外ではなく、クラスは実はclassクラスのインスタンスです。これはirbやpryでクラスを作って確かめてみるとわかります。
先ほど定義したclass Aのクラスを確かめてみると…
pry(main)> A.class => Class
.classはオブジェクトがどのクラスのインスタンスか確かめるためのメソッドです。結果はClassとなっていますので、AのクラスはClassクラスですね。
そんなはずはないと思う方はご自身でclass定義して確かめてみてください。
次に定数に代入しているということについて見ていきます。Rubyではアルファベットの大文字から始まる変数は定数となります。クラス定義ではみなさんアルファベットの大文字から始めると思います。
アルファベットの小文字から始めるとエラーになりますよね?
pry(main)> class a; end SyntaxError: (eval):2: class/module name must be CONSTANT class a; end ^
ここでエラーメッセージをよく見ればわかるのですが、"class/module name must be CONSTANT class"と言われています。
つまり、クラス定義は定数のクラスじゃないといけないよと言っています。先ほど、クラスはClassクラスのインスタンスだと言いました。
実はクラスはクラス定義された時にClassクラスに定数が定義されます。実際に偶然ではありえないクラス名をつけて確かめてみましょう。
(class Aだとたまたまかもしれないから念のため)
pry(main)> class HogeFugaGoGo pry(main)* def go pry(main)* puts 'go' pry(main)* end pry(main)* end => :go pry(main)> Class.const_defined?(:HogeFugaGoGo) => true
const_defined?はクラスやモジュールに定数が定義されているか、確認するメソッドです。
意味わからないクラス名ですが、classクラスに定数定義されていることが確認できました。
まとめ
これまでの検証からクラス定義がやっていることは以下の二つだとわかりました。
・Classクラスのインスタンスを作成する
・Classクラスに定数を定義する
これをもっと一般的に書くと下記をやっているということになります。
A = Class.new do def hoge puts 'hoge' end end
Aという定数にClassのインスタンスを代入しているということです。
クラス定義はその際に少し特別なことをして、Classクラスに定数への参照を加えています。
なので、クラス定義式を使わなければ、小文字でもクラスを作れます。
pry(main)> a = Class.new do pry(main)* def age pry(main)* puts 'age' pry(main)* end pry(main)* end => #<Class:0x00007ff5333d5f10> pry(main)> a.new.age age
こんな感じで。
ちなみにここら辺の説明はメタプログラミングRubyの5章に詳しく書いてあります。
もし興味のある方は読んでみてください。
終わりに
Rubyのクラス定義についてまとめました。
次回はメソッド探索についてまとめたいと思います。