2014-03-06 56 views
0

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

據我所知,它與綁定和如何方法和對象綁定到做上課。我不明白的是,如何在A內訪問C,但不是當我評估block時。我希望他們在相同的範圍內。

謝謝!

回答

2

在下面的代碼

A.new do 
    hello 
    C.new 
end 

你要創建的C的對象,如果是在類Object的範圍界定。不它不是。類C在模塊B的範圍內定義。你需要明確告訴B:C.new

上面的解釋是針對錯誤- :25:在'block in'中:未初始化的常量C(NameError)

我無法理解的是,我如何在A中訪問C?

Module#constants有答案給你: -

返回訪問的常量的名稱在MOD的數組。這包括常量在任何包含的模塊中的名稱(示例在開始節),除非繼承參數設置爲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] 

希望有所幫助。

+0

謝謝。這確實使得它更容易理解錯誤。有沒有什麼辦法可以做到這一點,而不必指定完整的命名空間? –