読者です 読者をやめる 読者になる 読者になる

【Ruby】Goldリベンジするぞ-メタプロRuby4.1クラス定義

メタプロRubyをしっかり読んで理解していこうと思います。

メタプログラミングRuby

メタプログラミングRuby

4.1.2カレントクラス

Rubyにはカレントオブジェクト(self)カレントクラスなるものがある。これらのパラメータは常に存在してる。たとえば以下の超単純なコードだと

def chk_current
  self
end
puts Object.private_methods.detect {|e| e == :chk_current}
# => :chk_current
p chk_current
# => main

カレントオブジェクトはメソッドの呼び出し側(と考えて良い)。カレントクラスはメソッドを定義した時にそのメソッドが格納されるクラス(と考えて良い)。この場合カレントオブジェクトはmain、カレントクラスはObjectである。(mainに関しては他のクラス定義と異なり少し特殊。)

もう一つ例を見る。カレントクラスとカレントオブジェクトの挙動が少し異なる例。

class MyClass
  def m_1
    p self
    def m_2; "hello"; end
  end
end

class MyClass2 < MyClass
end

obj = MyClass.new
obj2 = MyClass2.new
obj2.m_1 #=>#<MyClass2:0x007fc43a9f6608>
p obj.public_methods(false) # [:m_1, :m_2]
p obj2.public_methods(false) # []

サブクラスのオブジェクトからメソッドを定義する内容を含むメソッドを呼ぶ。
カレントクラス→MyClass、カレントオブジェクト→MyClass2
この辺を知るとやはりRubyは複雑だなと思いますね…。

class_evalを使うとカレントクラスをいじれます。

def add_method_to(a_class)
  a_class.class_eval do
    def m
      "hello"
    end
  end
end

add_method_to String
p "a".m #=> "hello"

正確にはカレントクラスとselfを、全体の辻褄を合わせる形で変更します。
カレントクラスを意識した変数、クラスインスタンス変数(Classクラスのインスタンスとしてのインスタンス変数?)に関してはこの次に!