wakasa5の日記

駆け出しエンジニアの勉強録

Rubyのクラスについて(1)クラス定義

最近、メタプログラミングRubyRubyの仕組みを読んでクラスについて勉強しているので、備忘録がてら内容をまとめておきます。


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のクラス定義についてまとめました。


次回はメソッド探索についてまとめたいと思います。