0

我遇到了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 `'

我知道它与绑定以及方法和对象如何绑定到类有关。我无法理解的是我为什么可以访问Cinside A,而不是当我评估block. 我希望它们在同一范围内。

谢谢!

4

1 回答 1

2

在下面的代码中

A.new do
  hello
  C.new
end

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

以上解释是针对错误-:25:in 'block in ': uninitialized constant 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]

希望有帮助。

于 2014-03-06T18:27:51.543 回答