gensym

プログラミングと読書、勉強に関するメモ

メタプログラミングRuby その8 [学習メモ]

メタプログラミングRuby 第2版

メタプログラミングRuby 第2版

第5章 木曜日 : クラス定義

5.1.2 カレントクラス

ruby プログラムが常にカレントオブジェクト self を持っているように、カレントクラス(モジュール)も持っている。
しかしカレントクラスには self のように直接アクセスできるキーワードはない。
class_eval 関数は与えられたクラスのコンテキストでブロックを評価することが出来る。

def add_method_to(cl)
  cl.class_eval do
    def m; 'Hello'; end
  end
end

add_method_to "abc".class
"abc".m
# => Hello

class でクラスを再オープンして同様のことをするにはクラス名の定数が必要だが、 class_eval の場合は変数を受けとることが出来るので、動的なメソッド定義が可能になる。
また class_eval はフラットスコープなので、ブロック外部の値を使うことが出来る。

5.1.3 クラスインスタンス変数

ruby における self はわかりにくい。
python の様に頻出するわけではないが、それ故に役割が見えにくくなる。
self は自身のクラスであり、インスタンスとは関係がない。なので

class MyClass
  @name = "Tom"
  def self.hello
    puts "hello, #{@name}!"
  end
end

MyClass.hello "Tom"
# => Hello, Tom!

となる。インスタンスを作ってから呼び出すわけではない。

5.3 特異メソッド

特異メソッドとは、特定のオブジェクトに特異的に定義されるメソッドだ。

name = "Alice"

def name.hello
  puts "hello, #{name}!"
end

name.hello
# => Hello, Alice!

使い方が難しいような特異メソッドだが、本質的にクラスメソッドと同じもので、定義も同じようにできる。

def obj.singleton_method; end
# 特異メソッド
def MyClass.class_method; end
# クラスメソッド