• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

ruby中的class_eval

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

最近几天在做一个ruby作业的时候遇到了一些问题,题目是这样要求的

class Class
  def attr_accessor_with_history(attr_name)
    attr_name = attr_name.to_s
    attr_reader attr_name
    attr_reader attr_name + "_history"
    
    class_eval %Q{ }
  end
end
 
class Foo
  attr_accessor_with_history :bar
  attr_accessor_with_history :baw
end

  

 
要求自己写一个访问器属性,可以记录下来该属性所描述的类中数据成员的所有历史值(原谅我对ruby从没有系统学习过,所以只有用自己在c++或者c#中知道的术语来描述)。
 
由于是在编译阶段就自动生成相应方法,所以这里就用了class_eval 函数。
 
尽管对语言不熟悉,但是我还是在一开始初步形成思路,也就是在class_eval 中添加一个方法模板,使得每个有该属性attr_accessor_with_history (或者说关键字?)的属性的类都自动的生成一个相关的setter,在setter中进行对历史值列表的维护。
 
想起来固然简单,但是由于对ruby的符号和元编程都毫无了解,实际开始操作的时候就发现了其中有很多没办法忽视的问题。
 
第一,我应该如何在class_eval 的字符串参数中访问到只知道变量名字字符串的变量?
经过一番学习之后,了解到了在编译阶段,会自动的将#{str}替换成str对应的变量,知道了这些,就方便了很多。
至少了解到该如何define这个setter的模板。
      def #{attr_name}=(value)      
      end

  

 
第二,在这个参数内部如何访问类的成员又成了一个问题,尤其是访问成员的历史值数组。
经过多次尝试,以及对手册又多次理解,发现这个问题其实跟上一个是相同的,由于#{str}只是一种格式,其中的str是任何返回值为字符串的表达式都可以自动替换成相应变量。
所以就简单的写了一个if就搞定了。
        if #{attr_name} == nil then       
          @#{(attr_name + "_history")} = Array.new
          @#{(attr_name + "_history")}.push(nil)
        end
 
        @#{attr_name} = value
        @#{(attr_name + "_history")}.push(value)    

  


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
RubyString发布时间:2022-07-14
下一篇:
ruby on rails 数据库操作发布时间:2022-07-14
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap