论坛首页 编程语言技术论坛

Advanced Rails -- Ruby 基本技术(9) -- 元编程技巧4

浏览 1978 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-06-09  
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.extended和Class.inherited的方法得到,这些不会有ObjectSpace更切实。
   发表时间:2008-06-10  
可能是本人水平有限的原因,看了advanced Rails的系列,感觉很难受,很多看不懂
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics