Advanced Rails--Ruby基本技術(9)--メタプログラミングテクニック4


Introspection and ObjectSpace: Examining Data and Methods at Runtime
Rubyは、実行時にオブジェクトを検索するための多くの方法を提供します.インスタンス変数オブジェクトにアクセスする方法もあります.彼らを使うときは気をつけてください.これらの方法は
パッケージを破壊しました.

	class C
	  def initialize
	    @ivar = 1
	  end
	end

	c = C.new
	c.instance_variables              # => ["@ivar"]
	c.instance_variable_get(:@ivar)   # => 1
	
	c.instance_variable_set(:@ivar, 3) # => 3
	c.instance_variable_get(:@ivar)    # => 3

Object methodsメソッドは、受信者に定義された単一のメソッドを含むインスタンスメソッドの配列を返します.この方法の最初のパラメータが
falseでは、オブジェクトの単一のメソッドのみが返されます.

	class C
	  def inst_method
	  end

	  def self.cls_method
	  end
	end

	c = C.new

	class << c
	  def singleton_method
	  end
	end

	c.methods - Object.methods # => ["inst_method", "singleton_method"]
	c.methods(false) # => ["singleton_method"]

Module#instance_methodsはクラスまたはモジュールのインスタンスメソッドを返します.instance_methodsはclassによって呼び出され、methodsはインスタンスによって呼び出されます.
使用します.instance_へmethodsはfalseが親クラスをスキップした方法を渡します.

	C.instance_methods(false) # => ["inst_method"] 

MetaidのmetaclassでCのクラスメソッドをチェックすることもできます.

	C.metaclass.instance_methods(false) # => ["new", "allocate", "cls_method",
	                                          "superclass"]

In my experience, most of the value from these methods is in satisfying curiosity. With the
exception of a few well-established idioms, there is rarely a need in production code to reflect on
an object's methods. Far more often, these techniques can be used at a console prompt to find
methods available on an object—it's usually quicker than reaching for a reference book:

	Array.instance_methods.grep /sort/ # => ["sort!", "sort", "sort_by"]

ObjectSpace
ObjectSpaceはRubyのオブジェクトシステムと対話するためのモジュールである.最下位のhackingをより簡単にできるいくつかのモジュールメソッドがあります.
    Garbage-collection methods: define_finalizer (sets up a callback to be called just before an object is destroyed), undefine_finalizer (removes those call-backs), and garbage_collect (starts garbage collection).
    _id2ref converts an object's ID to a reference to that Ruby object.
    each_object iterates through all objects (or all objects of a certain class) and yields them to a block.
これらの方法は役に立つが、危険だ.彼らを慎重に使う.
RubyのTest::UnitフレームワークにObjectspaceを適切に使用する例があります.コードはObjectSpaceを使用しています.each_objectは、Test::Unit::TestCaseクラスから継承されたすべての存在を列挙する.

	test_classes = []
	ObjectSpace.each_object(Class) {
	  | klass |
	  test_classes << klass if (Test::Unit::TestCase > klass)
	}

だめなのは、ObjectSpaceがRubyの仮想マシンであることがさらに複雑化していることです.特にObjectSpaceを開くとJrubyのパフォーマンスが損なわれます.Rubyの解析器はJVMの内部データの存在を直接チェックできないためです.逆に、JRubyは手動でオブジェクトを追跡する必要があり、これにより多くの消費が増加します.同じテクニックでModuleのように义齿Inheritedの方法は、ObjectSpaceがより確実ではないことを得た.