メタプログラミングについての本を読んでいるので、読んだ部分を忘れないように自分でまとめます。
参照文献:「メタプログラミング Ruby 第二版」 オライリー・ジャパン / Paolo perrotta 著
メタプログラミング
メタプログラミングとは,コードを記述するコードを記述することである。
インストロペクション
変数、クラス、メソッドなどを 言語要素(language constructs) と呼ぶ。
Ruby言語では、言語要素に質問できることができる。これをインストロペクションと呼ぶ。
どういうことかというと、例えば以下のようなクラスがあったとする。
同時にクラスのインスタンスも生成した場合、それについてのクラスを聞くと教えてくれます。
class Helloworld
def initialize(text)
@text = text
end
def first
@text
end
end
object = Helloworld.new("helloworld")
object.class # => Helloworld
また、クラスにインスタンスメソッドの一覧を聞くこともできる。
class Helloworld
def initialize(text)
@text = text
end
def first
@text
end
end
object = Helloworld.new("helloworld")
object.class # => Helloworld
object.class.instance_methods(false) # => [:first]
*ここで引数のfalseは、自分のクラスに定義されたインスタンスメソッドの一覧を表示させるだけで、継承したものはださないという意味です。
更に、インスタンス変数についても教えてくれる。
class Helloworld
def initialize(text)
@text = text
end
def first
@text
end
end
object = Helloworld.new("helloworld")
object.class # => Helloworld
object.class.instance_methods(false) # => [:first]
object.instance_variables # => [:@text]
オープンクラス
オープンクラスについての簡単なまとめ。
class Open
def x
puts "x"
end
end
class Open
def y
puts "y"
end
end
obj = Open.new
obj.x #=> "x"
obj.y #=> "y"
なにが起きているのかまとめると、
先ずはじめのclass Openが読み込まれた段階では、class Openは存在していない。すると当然、クラス Openは作成されます。そしてその後、xメソッドが定義されています。
しかし、二回目のclass Openの段階ではすでにOpenクラスが存在しているので改めて定義されません。その代わり、既存のクラスを再オープンして、 yメソッド追加します。
つまり、いつでも既存のクラスを再オープンし、メソッドを追加できます。
この技法のことはオープンクラスと呼びます。
オープンクラスの問題点
オープンクラスの問題点として有名なのが、既存のクラスを再オープンし、メソッドを追加するときに、そのメソッド名が既に存在しているときである。
この場合、既存のメソッドを上書きしてしまい、どこかでそのメソッドが使われているところでバグが起きてしまいます。
これようなことをモンキーパッチと呼びます。
class Open
def x
puts "x"
end
end
class Open
def x
puts "y"
end
end
obj = Open.new
obj.x #=> "y" ←上書きされている
これは、Openクラスを再オープンし、メソッドxを上書きしています。