分享

Meta-Programming in Ruby: 动态生成class,并添加attribute和method。 - AllenYoung - JavaEye技术网站

 shaobin0604@163.com 2008-11-24
Ruby的动态语言特性和强大的meta-programming模型一直是让我这种Java程序员唏嘘感慨。看着RoR可以实现那么多魔术般的事情而不费吹灰之力,我着实想好好学学Ruby的meta-programming。可惜这方面资料好像比较少(至少我是没有找到什么好的,JavaEye这里讨论的也不多),我只能硬着头皮自己慢慢摸索。这篇文章只能算是一个最简单的入门,给大家展示一下Ruby中的meta-programming大概是什么样子。

下面代码大概会做一下事情:
  1. 根据指定的txt文件动态创建一个class,例如“people.txt”会被创建为People。
  2. txt文件的第一行是以“,”分隔的字符串,我会把它们作为class的属性动态加入class。
  3. 动态声明class的initialize方法和to_s方法。
代码如下:
ruby 代码
 
  1. class MetaProgrammingTest  
  2.     
  3.   # class method,用来根据给定的文件动态创建一个新的class。  
  4.   def self.create_class(file_name)  
  5.     # 去掉文件的扩展名.txt,并令首字母大写。例如"people.txt" -> 'People'    
  6.     class_name = File.basename(file_name,".txt").capitalize  
  7.     # 动态创建一个class,并使用class_name对其命名。  
  8.     klass = Object.const_set(class_name,Class.new)  
  9.       
  10.     # 读取文件的第一行,并以","为分隔符把每个token放到数组names中。  
  11.     first_line = ''  
  12.     File.open(file_name) { |io| first_line = io.gets.chomp }  
  13.     names = first_line.split(",")  
  14.       
  15.     # class_eval会执行其closure中的代码。  
  16.     klass.class_eval do  
  17.       # 把names数组中所有的字符串声明为class的attribute。  
  18.       # 注意:这里做了2两件事情,声明了这些attribute,并创建了get和set这些attribute的方法。  
  19.       attr_accessor *names  
  20.         
  21.       # define_method用来定义class的instance method。
  22.       # 参数是方法名,后面的closure是方法体,closure的参数就是方法的参数。  
  23.       define_method(:initializedo |*values|  
  24.         # 对class的每个attribute,用传入的参数进行赋值。  
  25.         names.each_with_index do |name,i|   
  26.           instance_variable_set("@"+name, values[i])  
  27.         end  
  28.       end  
  29.         
  30.       # 定义to_s方法。  
  31.       # self.class返回当前对象的class(即"People")
  32.       # self.send()得到其参数代表的attribute的值。  
  33.       define_method(:to_sdo  
  34.         str = "[#{self.class}:"  
  35.         names.each {|name| str << " #{name}=#{self.send(name)}" }  
  36.         str + "]"  
  37.       end  
  38.         
  39.     end  
  40.       
  41.     # 返回这个动态创建的类。  
  42.     klass  
  43.   end  
  44.     
  45. end  
  46.   
  47. # 测试代码  
  48. klass = MetaProgrammingTest.create_class('people.txt') # "people.txt"的内容为"id,name,age"  
  49. klass_instance = klass.new('001', 'Allen Young', 23)  
  50. puts klass_instance.to_s    
  51. # 输出  
  52. puts klass_instance.inspect
  53. # 输出#  

怎么样?真的是非常强大吧。如果什么时候,Java也能有这么强大的meta-programming就好了

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多