【问题标题】:Need help with reflection example from "The Ruby Programming Language"需要“The Ruby Programming Language”中的反射示例帮助
【发布时间】:2009-09-07 07:43:38
【问题描述】:

Ruby 编程语言 (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")

【问题讨论】:

    标签: ruby reflection


    【解决方案1】:

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

    不幸的是,它没有那么简单。

    首先仔细看看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
    

    【讨论】:

      【解决方案2】:

      这是一般主题:

      使用 ClassName.instance_eval 来定义 单例方法。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多