instance_eval和class<<之间的区别自?

时间:2011-04-27 13:58:05

标签: ruby

我似乎无法掌握这两种“结构”之间的确切差异。在我看来,下面的小脚本应该输出三次相同的东西:

class Example
  puts self

  class << self
    puts self
  end

  instance_eval do
    puts self
  end
end

然而,输出是:

Example
#<Class:Example>
Example

这是我的理由:

  • ExampleClass的一个实例,因此类主体中的self指的是那个;
  • class << objself设置为给定块中的obj,在我的情况下,Class的实例为Example(这是instance_eval我可能错了);
  • class << self在给定的实例中运行块,因此,在我的情况下,它与将块中的代码直接放在类主体中几乎相同。

我目前的猜测是,ExampleClass#<Class:Example>之间插入一个幽灵等级,并将自设置为,但{{1}}的输出并未确认

那么我的理由是什么问题?

2 个答案:

答案 0 :(得分:6)

  

class << objself设置为给定块中的obj,在我的情况下,Class的实例为Example(这是class << obj我可能错了);

不,obj打开self单件类。正如您正确指出的那样,在类声明中,self引用了类本身,因此,在这种情况下,“内部”puts(即传递给Example的那个)指的是{{1}}的单身类

答案 1 :(得分:3)

在我看来,class << self一直是Ruby中最令人讨厌的语法之一。除了货物崇拜惯例之外,对语言不熟悉的人几乎不知道这意味着什么,即使是那些非常熟悉语言的人也只是对instance_method区别于什么的朦胧理解,因为这两者似乎是非常相似。

以下是定义类方法的两种不同方法的示例:

class Example
  class << self
    def class_def
      :class_def
    end
  end

  instance_eval do
    def instance_def
      :instance_def
    end
  end
end

您可以通过调用方法来检查这些是否有效:

puts Example.class_def.inspect
# => :class_def
puts Example.instance_def.inspect
# => :instance_def

区别在于您使用define_method动态创建方法,因为instance_eval版本的绑定似乎不正确:

class Example
  class << self
    define_method(:class_def) do
      :class_def
    end
  end

  instance_eval do
    define_method(:instance_def) do
      :instance_def
    end
  end
end

这导致定义了instance_def方法,但没有绑定到类本身:

puts Example.class_def.inspect
# => :class_def
puts Example.instance_def.inspect
# => NoMethodError: undefined method ‘instance_def’ for Example:Class

创建动态方法的唯一可靠方法是使用class << self。方法instance_def似乎被创建并丢弃,因为即使在该块中,它也没有显示在Example.methods中。