Instance_eval无权访问模块中的类

时间:2014-03-06 18:25:02

标签: ruby binding module scope instance-eval

我遇到了instance_eval和模块包含的问题。

请查看以下代码:


module B
  class C
    def initialize
      puts 'This is C'
    end
  end

  def hello
    puts 'hello'
  end
end

class A
  include B

  def initialize(&block)
    hello
    C.new
    instance_eval(&block)
  end
end

A.new do
  hello
  C.new
end

当我运行此代码时,我得到了


hello
This is C
hello
-:25:in `block in ': uninitialized constant C (NameError)
    from -:19:in `instance_eval'
    from -:19:in `initialize'
    from -:23:in `new'
    from -:23:in `'

我知道它与绑定以及方法和对象如何绑定到类有关。我无法理解的是,如何在C内访问A,但在我评估block时却无法访问{{1}}。我希望它们属于同一范围。

谢谢!

1 个答案:

答案 0 :(得分:2)

在下面的代码中

A.new do
  hello
  C.new
end

您正在尝试创建C的对象,就好像它是在类Object的范围内定义的一样。不它不是。类C的定义在模块B的范围内定义。你需要明确地告诉B:C.new

以上解释是针对错误 - :25:in'block in':未初始化的常量C(NameError)

  

我无法理解的是如何在A中访问C?

Module#constants为您解答: -

  

返回 mod 中可访问的常量名称数组。除非将inherit参数设置为false,否则这包括任何包含的模块中的常量的名称(示例在部分的开头)。

看一下例子:

module M
  X = 10
  class D; Y = 10 ;end
end
class C
  include M
  def initialize
    p self.class.constants
  end
end

C.new
# >> [:X, :D]

现在申请你的例子:

module B
  class C
    def initialize
      'This is C'
    end
  end

  def hello
    'hello'
  end
end

class A
  include B

  def initialize(&block)
    p self.class.constants
    C.new  # it will work
    #instance_eval(&block)
  end
end

A.new do
  hello
  C.new # but this will throw error.
end

# it confirms that C is accessible, within the method.
# That is the same reason you got the output "This is C"
# >> [:C]

希望有所帮助。