需要有关“The Ruby Programming Language"中的反射示例的帮助; [英] Need help with reflection example from "The Ruby Programming Language"

查看:46
本文介绍了需要有关“The Ruby Programming Language"中的反射示例的帮助;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In this example from The Ruby Programming Language (p.270), I'm confused why the instance_eval method on the last line of the sample code defines a class method called String.empty.

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

Don't you use class_eval to define a class method and instance_eval when you want to define an instance method?

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")

推荐答案

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

Don't you use class_eval to define a class method and instance_eval when you want to define an instance method?

不幸的是,事情并没有那么简单.

Unfortunately, it is not as straightforward as that.

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

First take a closer look at what the examples of class_eval are doing. class_eval is a method which comes from Ruby's module class so can be called on any class or module. When you use String.class_eval you are evaluating the given code in the context of the class. i.e. when you write String.class_eval("def len; size; end") it's exactly like you reopened the class and typed the code passed to class_eval e.g.

class String
  def len
    size
  end
end

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

Thus to add a class method using class_eval you would write String.class_eval("def self.empty; ''; end") which has the same effect as:

class String
  def self.empty
    ''
  end
end

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

instance_eval is defined in Ruby's Object class so is available on any Ruby object. In the general case it can be used to add a method to a specific instance. e.g. if we have a String str and say:

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

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

Then this will alias special to size just for str but not for any other String object:

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 的元类并键入传递的代码,例如

To understand what is going on with String.instance_eval remember that the class String is itself an object (an instance of the class Class) and that there is such a singleton instance object of every class defined. When you use String.instance_eval you are evaluating the given code in the context of the String instance object. i.e. it is equivalent to reopening String's metaclass and typing the code passed e.g.

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

这篇关于需要有关“The Ruby Programming Language"中的反射示例的帮助;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆