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

ono*_*ono 2 ruby reflection

在这个来自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")
Run Code Online (Sandbox Code Playgroud)

mik*_*kej 7

您是否用于class_eval定义类方法以及instance_eval何时要定义实例方法?

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

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

class String
  def len
    size
  end
end
Run Code Online (Sandbox Code Playgroud)

因此,要使用class_eval添加类方法,您将编写String.class_eval("def self.empty; ''; end")具有与以下相同效果的类方法:

class String
  def self.empty
    ''
  end
end
Run Code Online (Sandbox Code Playgroud)

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

str.instance_eval("def special; size; end")
Run Code Online (Sandbox Code Playgroud)

那么这将别名specialsize只是str,但没有任何其他String对象:

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

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

class String
  class << self
    def empty
      ''
    end
  end
end
Run Code Online (Sandbox Code Playgroud)