需要帮助“Ruby编程语言”中的反射示例

时间:2009-09-07 07:43:39

标签: ruby reflection

The Ruby Programming Language (p.270)的这个例子中,我很困惑为什么示例代码的最后一行的instance_eval方法定义了一个类方法名为String.empty

当您想要定义实例方法时,是否不使用class_eval来定义类方法和instance_eval

o.instance_eval("@x") # Return the value of o's instance variable @x

# Define an instance method len of String to return string length
String.class_eval("def len; size; end")

# Here's another way to do that
# The quoted code behaves just as if it was inside "class String" and "end"
String.class_eval("alias len size")

# Use instance_eval to define class method String.empty
# Note that quotes within quotes get a little tricky...
String.instance_eval("def empty; ''; end")

2 个答案:

答案 0 :(得分:7)

  

不要使用class_eval来定义   类方法和instance_eval时   你想定义一个实例方法吗?

不幸的是,它并不那么简单。

首先仔细看看class_eval的例子正在做什么。 class_eval是一种来自Ruby的module class的方法,因此可以在任何类或模块上调用。当您使用String.class_eval时,您正在评估类的上下文中的给定代码。即当你写String.class_eval("def len; size; end")时,就像你重新打开课程并输入传递给class_eval的代码一样,例如

class String
  def len
    size
  end
end

因此,要使用class_eval添加类方法,您可以编写String.class_eval("def self.empty; ''; end"),其效果如下:

class String
  def self.empty
    ''
  end
end

instance_eval在Ruby的Object class中定义,因此可以在任何Ruby对象上使用。在一般情况下,它可用于向特定实例添加方法。例如如果我们有一个字符串str并说:

str.instance_eval("def special; size; end")

然后,这会将special别名为size,仅用于str,但不能用于任何其他String对象:

irb(main):019:0> "other".special
NoMethodError: undefined method `special' for "other":String
        from (irb):19

要理解String.instance_eval发生了什么,请记住类String本身就是一个对象(类Class的一个实例),并且每个类都定义了这样一个单例实例对象。当您使用String.instance_eval时,您正在String实例对象的上下文中评估给定代码。即它等同于重新打开String的元类并输入传递的代码,例如。

class String
  class << self
    def empty
      ''
    end
  end
end

答案 1 :(得分:1)

这是一般主题:

  

使用ClassName.instance_eval进行定义   单身方法。

     

使用ClassName.class_eval来定义   实例方法。

post有一个非常简洁的解释,试一试......