在我看来,对于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)
有人会解释什么是问题,这背后的内部逻辑是什么。我非常感谢您提供的任何帮助。
答案 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"