メタプログラミングRuby クラス定義について


クラス定義

クラスにはメソッド以外にもあらゆるコードを記述できます。

class Example
  puts 'Hoge!'
end #=>Hoge!

result = class Example
  self
end

result #=> Example

クラス定義の中では、クラスがカレントオブジェクトになるんです。つまりselfになるんです。

クラスインスタンス変数

クラス定義の中で定義されたインスタンス変数のことをクラスインスタンス変数といいます。
実際にコードを見ていきましょう

class Example
  @var = 1
  def self.read; @var; end
  def write; @var = 2; end
  def read; @var; end
end

obj = Example.new
obj.read #=> nil
obj.write #=> 2
obj.read #=> 2
Example.read #=> 1

1つ目の@varobjがselfになるんです。objオブジェクトのインスタンス変数なんです。
2つ目の@varExampleがselfになるんです。Exampleクラスというオブジェクトのインスタンス変数なんです。

特異メソッド

特異メソッドとは特定のオブジェクトで参照できるメソッドのことを特異メソッドといいます。
たとえば、あるオブジェクトが本のタイトルかどうかを調べるメソッドを記述しましょう。

str = 'Qiitaのタイトルが入ります' #動的に文字列が入ると仮定してください

def str.title?
  self.upcase == self
end

str.title? #=> false

そして実はクラスメソッドも実は特異メソッドなんです。
以下の記事で詳しく解説しているのでご一読ください。

特異クラス

Rubyという言語は、オブジェクトにクラスを聞くとすべてを教えてくれるわけではないんです。
実は、オブジェクトは裏に特別なクラスを持っているんです。その特別なクラスが特異クラスと呼ばれるものなんです。
以下のコードを見てみましょう。

'abc'.singleton_class
=> #<Class:#<String:0x000001e1626b1378>>

ここから分かるのは特異クラスはクラスであることがわかるんです。
そしてインスタンスは1個しか持てないんです。
そして、1番大事なことは、特異クラスはオブジェクトの特異メソッドが存在する場所なんです。
ここを理解するにはRubyのオブジェクトモデルについて深く理解していかないといけないので見ていきましょう。

メソッド探索

以下のコードをもとにメソッド探索をしていきましょう

class C
  def a_method
    'a_methodが出力されます'
  end
end
    
class C
  class << self
    def singleton_a_method
      'singleton_a_methodが出力されます'
    end
  end
end

class D < C; end
obj = D.new
obj.a_method

class << obj
  def a_singleton_method
    'a_singleton_methodが出力されます'
  end
end


obj.singleton_class.superclass #=> D

C.singleton_class
D.singleton_class
D.singleton_class.superclass
C.singleton_class.superclass

図示すると以下のような図になります。

この図から分かる通り、特異クラスのスーパークラスがスーパークラスの特異クラスなんです。
Rubyという言語において、スーパークラスや特異クラスがなぜこのような配置になっているのでしょうか?
それは、このような配置することで子クラスからクラスメソッドを呼び出せるからなんです。

この本において、この章が1番難しいとおもいます。
抽象的な話が多いので個人的にはスゴイむずかしく感じました。

残りの数ページは次回にしようとおもいます

以上です。何か間違いがございましたら、ご教示いただけますと幸いです。

【参考資料】