メタプログラミングRuby二章(2.2途中まで)

第二章(途中まで)書きます。

オープンクラスとは?

既存のクラスを再定義することです。

以下のコードを見て下さい。

これはStringクラスのメソッドを拡張した例です。

class String
  def dokkiri!
    return "!"
  end
end
p "test".class  #String
p "test".dokkiri! #!

補足 オブジェクトとClass

僕はこの文読んだ時よくわからなかったです。 なんで、基本的なクラスの話を噛み砕いて説明します 上のソース例の「"test"」は文字列オブジェクトを示しています。 オブジェクトは様々なものありますが、 代表的なものは数値(1や100)、文字列、配列などがあります。

そしてオブジェクトはクラスに属しています。 直感的に言えば性質みたいなものでしょうか。 性質(クラス)に応じて文字列だから「大文字に変換」といった 性質(クラス)に合わせた機能(メソッド)が使えます。 オブジェクトが属するクラスを探すにはclassメソッドを使います。

今回用いたオープンクラスはclass Stringに属するメソッドを追加しました。

しかし、注意があります。

以下のコードを見て下さい。

p "test".capitalize #Test

class String
  def capitalize
    return self + "!"
  end
end

p "test".capitalize # "test!"

オープンクラスは既存のメソッド(capitalize)も変更出来るので 既存のプログラムの挙動が変わり、バグを引き起こすことがあります。 (モンキーパッチという) よって、取扱には十分注意です。

インスタンス変数とは?

インスタンス変数とはクラスをインスタンス化した際に用いる変数です。(先頭に@をつけます) インスタンス変数はクラスに属しているわけではなく、クラスのオブジェクトに紐付いています。

コード例を見てみます。

class Test
  def test
    @test = "test"
  end
end

obj = Test.new
p obj.instance_variables #インスタン変数なし

obj2 = Test.new
obj.test #@testを定義
p obj.instance_variables #@test

メソッド(ここではtest2)はクラスに属しているため、 クラス(Test)をインスタンス化(オブジェクト化)しただけでは、 メソッド(test)は呼び出されない。 直感的にいうと、Testクラスのインスタンス化はあくまでもメソッド(インスタンスメソッド)の リンクを使えるようにしただけといったところでしょうか。

インスタンス化してすぐにインスタンス変数を使うには 下のコードのようにinitializeメソッドを使う必要があります。

class Test2
  def initialize
    @test2 = "test2"
  end
end

obj3 = Test2.new
p obj3.instance_variables #@test2

自分の理解が不確かなところもあります。 もし、この記事をみている方で「違うぞ」と思った方は コメントお願い致します。