包含在ruby特征类中的模块

时间:2014-12-12 07:05:06

标签: ruby class module metaprogramming

在我看来,对于instance_eval,类范围变为单例类,也称为目标对象的本征类。因此,在对象的单例类上创建的实例方法将成为该对象的单例方法。我的意思是以下两个代码片段产生预期的结果

class TestClass; end

使用特征类

class TestClass
  class << self   
    def class_method
      "class_method of TestClass"
    end
  end
end

使用instance_eval

TestClass.instance_eval do
 def class_method2
   "class_method of TestClass"
 end
end

因此我们可以调用TestClass.class_method和TestClass.class_method2并获得相应的结果。 现在让我们假设我们有一个模块TestModule

module TestModule
  def instance_method
    " instance_method from TestModule"
  end
end

现在如果我们在特征类中包含这个模块,那么我们可以访问instance_method作为TestClass的类方法

class TestClass
  class << self   
    include TestModule
  end
end

因此,TestClass.instance_method将按预期工作。

但是如果我们使用instance_eval执行相同的操作,则会失败。请检查以下代码段

TestClass.instance_eval do
  include TestModule
end

当我尝试调用TestClass.instance_method时,我收到以下错误。

ArgumentError: wrong number of arguments(0 for 1)

有人会解释什么是问题,这背后的内部逻辑是什么。我非常感谢您提供的任何帮助。

1 个答案:

答案 0 :(得分:3)

这是因为如果您使用include,那么当前类是什么并不重要,但self指向的是什么(include是如果您未指定显式接收方,则在self上调用此方法,并且在您的示例中,self指向TestClass,因此TestModule#instance_method成为TestClass的实例方法},如下例所示:

class TestClass
end

module TestModule
  def test_method
    'test'
  end
end
TestClass.instance_eval { include TestModule }
TestClass.new.test_method
# => "test"