Ruby中的class_eval方法以及__FILE__和__LINE__参数

原文:Ruby class_eval, FILE and LINE arguments
这里我们将讨论一个class_eval调用的例子

def my_attr_reader(sym)
    class_eval <<-READER, __FILE__ , __LINE__ + 1
        def #{sym}
            @#{sym}
         end
    READER
end

class_eval方法用来做什么呢?为什么向它传递文件名和行号?这些是我们接下来要回答的问题。

class_eval在接受者的上下文中对字符串或块进行计算,接受者可以为class或module。
在下面的例子中,我们使用class_eval为self(User类)定义实例方法:

module MyAttrReader
  def my_attr_reader(sym)
    class_eval <<-READER, __FILE__ , __LINE__ + 1
      def #{sym}
        @#{sym}
      end
    READER
  end
end

class User
  extend MyAttrReader

  def initialize(name)
    @name = name
  end

  my_attr_reader :name
end

u = User.new('dalibor')
p u.name # calls the method 'name' defined with class_eval

现在我们来解释上段代码中使用的伪变量

__FILE__ # the current source file name.当前文件名称
__LINE__ # the current line number in the source file.当前行号

我们可以将class_eval调用简化为以下形式:

def my_attr_reader(sym)
  class_eval("def #{sym}; undefined_method; @#{sym}; end;", __FILE__ , __LINE__ )
end 

现在语法很清晰了,我们查看文档中关于class_eval的说明发现,第二和第三个参数用来对错误消息进行设置,以便方便我们对错误进行定位。

来看看下面这两段代码产生的错误。注意我们在class_eval计算的字符串中添加了undefined_method,并且在第一段代码中移除了file和line这两个伪变量:

snippet1:
module MyAttrReader
  def my_attr_reader(sym)
    class_eval "def #{sym}; undefined_method; @#{sym}; end;"
  end
end

class User
  extend MyAttrReader

  def initialize(name)
    @name = name
  end

  my_attr_reader :name
end

u = User.new('dalibor')
p u.name

# (eval):1:in `name': undefined local variable or method `undefined_method' for # (NameError)
snippet2:
module MyAttrReader
  def my_attr_reader(sym)
    class_eval "def #{sym}; undefined_method; @#{sym}; end;", __FILE__ , __LINE__
  end
end

class User
  extend MyAttrReader

  def initialize(name)
    @name = name
  end

  my_attr_reader :name
end

u = User.new('dalibor')
p u.name

# t.rb:3:in `name': undefined local variable or method `undefined_method' for # (NameError)

报错信息见代码块底部。
可以注意到第二段代码的报错信息更加明确,阐明了错误发生在t.rb文件的第三行,但是第一段代码在错误发生时并没有给出类似的错误定位信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值