Ruby元编程起步2_Ruby_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > Ruby > Ruby元编程起步2

Ruby元编程起步2

 2012/6/18 16:27:16  piecehealth  程序员俱乐部  我要评论(0)
  • 摘要:书接上回……不过要先打个岔……动态语言就是要动起来Ruby被人说上亿遍是动态语言,所以咱就要动态给你们看Array.class_evaldodefpunch_horse_assputs"Piecehealthisaverytall,richandhandsomeman!!!"enddefsay_truthputs"OK,fine,acutallyI'madiaosi"endend[1,2,3].punch_horse_assArray.class_eval{remove_method
  • 标签:Ruby 编程
书接上回……
不过要先打个岔……

动态语言就是要动起来

Ruby被人说上亿遍是动态语言,所以咱就要动态给你们看

Array.class_eval do
  
  def punch_horse_ass
    puts "Piecehealth is a very tall, rich and handsome man!!!"
  end
  
  def say_truth
    puts "OK, fine, acutally I'm a diaosi"
  end

end

[1, 2, 3].punch_horse_ass

Array.class_eval {remove_method :say_truth}

[1, 2, 3].say_truth # undefined method `say_truth' for [1, 2, 3]:Array (NoMethodError)


上面这段代码只想表达,我们可以对一个类在任何时候为所欲为(说这个词的时候总是不自觉露出淫 荡的表情),于是,我们就要对刚才那个还非常嫩的类为所欲为了!

实现initialize方法:
这一步感觉没什么好说的,直接上代码吧
module Tool

  def self.csv2class csv_name 
    klass_name = csv_name.gsub('.csv', '').gsub(/\s+/, '_').downcase.capitalize
    klass = Object.const_set(klass_name, Class.new)
    File.open(csv_name ) do |file|
      attributes = file.readline.chomp.split(',')
      
      klass.class_eval do
        
        attr_accessor *attributes
        
        define_method :initialize do |*args| 
          attributes.each_with_index do |attribute, i|
            instance_variable_set("@#{attribute}", args[i])
          end
        end
      
      end
    
    end
 
 end

end

Tool.csv2class "Friends.csv"
puts Friends.new('Lilei','M',26,'Worker').dept


相信有一定ruby基础的同学能看明白(看不明白的同学不用担心,上面的东西baidu google类似的内容很多,搜索一下吧),但是这些是经过我实践后得到的最佳解决方案。

我第一次接触这个时主要面临两个问题,我们一个一个说吧。
第一个是为什么一定要用define_method而不直接用def(像第一段代码一样),这样做除了装X还有什么好处?
好吧,为了不被雷劈,我们把define_method方法换成def,即
        def initialize *args 
          attributes.each_with_index do |attribute, i|
           instance_variable_set("@#{attribute}", args[i])
         end
        end


然后运行Tool.csv2class "Friends.csv"的时候报错:in `initialize': undefined local variable or method `attributes' for #<Friends:0x35b46d8> (NameError)

啊,原来class_eval相当于打开一个内环境,而attributes是内环境之外的,也就是说class_eval内外是两个不同的作用域,而且貌似没什么交集。

这就是我第二个问题,内环境外环境是如何交互的?
很显然用defing_method可以用到外面作用域的变量跟方法,而class_eval里面的实例变量,类变量赋值取值可以用instance_variable_set, instance_variable_get, class_variable_set, class_variable_get来实现,这样两套不同的体系在两个不同的作用域间各自运作,又可以相互通讯,实在是太妙了……貌似还缺一个洋气的名字,就叫扁平作用域吧!


(由于本人比较懒,写的时候随手写的,也没查阅什么资料,绝大部分都是凭借记忆,很多表达都不准确,只希望能帮大家理解元编程的一些东西)
发表评论
用户名: 匿名