【转】Ruby 中如何动态生成类
by circleoflife on 周二, 10/07/2008 - 10:52
最近在研究Watir的自动化测试,有了成果写文章上来。先转一个帖子:
转自:http://www.coolcode.cn/show-303-1.html
Ruby 中如何动态生成类
废话不多说,先看例子:
Ruby代码
- Object.module_eval("class Test1\nend")
- x = Object.const_get("Test1".to_sym)
- x.method(:attr_accessor).call("test1".to_sym)
- x.method(:public).call("test1".to_sym)
- x.method(:public).call("test1=".to_sym)
- x.method(:attr_accessor).call("test2".to_sym)
- x.method(:public).call("test2".to_sym)
- x.method(:public).call("test2=".to_sym)
- x.method(:attr_accessor).call("test3".to_sym)
- x.method(:public).call("test3".to_sym)
- x.method(:public).call("test3=".to_sym)
- y = Test1.new # also can use x.new
- y.test1 = 'Hello'
- y.test2 = 'Ruby'
- y.test3 = 1.86
- puts y.class
- puts y.test1, y.test2, y.test3
原理就是利用 module_eval 定义一个空类,然后利用 const_get 获取到该类的引用,最后利用反射机制调用 attr_accessor、public 等方法完成类的定义。
这样做有什么好处呢?好处是,只要我们知道类名及其属性名,就可以动态的创建一个类,这在反序列化未知类的对象时是非常有用的。
但是上面的方法看上去还是比较麻烦,下面定义一个通用的:
Ruby代码
- class Object
- def self.attr_add(*symbols)
- symbols.each { |sym|
- self.send(:attr_accessor, sym)
- self.send(:public, sym, sym.to_s.concat('=').to_sym)
- }
- self
- end
- def self.define_class(name, *attrs)
- (name.split('::').inject(self) { |x, y| x.const_set(y, Class.new) }).attr_add(*attrs)
- end
- def self.class_get(name)
- name.split("::").inject(self) {|x,y| x.const_get(y) }
- end
- end
现在用 define_class 定义类,用 class_get 获取类就方便多了。
- circleoflife's blog
- 要发表评论,请先登录 或 注册
标签云
感谢您关注我的个人博客!
为了您的更好的阅读和留言,建议您注册用户,这样您可以获得更大的权限,以及更方便的留言。
注册只需要一分钟的时间。但是您需要提供您的邮箱。注册后,密码会自动发到您的邮箱,请在第一次登录时修改。
我承诺不会将您的Email泄露给他人,或者发送垃圾邮件。