2012-12-31 16 views
0

很抱歉的模糊問題的標題,但我不知道是什麼原因導致了以下內容:重寫namespaced puts只有在覆蓋Kernel.puts後才起作用?

module Capistrano 
    class Configuration 
    def puts string 
     ::Kernel.puts 'test' 
    end 
    end 
end 

現在,當調用Capistrano的puts,我沒有看到「測試」,但我看到原來的輸出。

然而,當我還補充一點:

module Kernel 
    def puts string 
    ::Kernel.puts 'what gives?' 
    end 
end 

現在,突然之間,puts實際上返回 「測試」,而不是 「怎麼辦?」,而不是原來的內容,但 「測試」。

是否有合理的解釋爲什麼會發生這種情況(除了我對Ruby內核內部工作的有限理解之外)?

事情看起來關閉,我(但不知何故「似乎工作」):

  • 我希望第一個塊返回「測試」,但它沒有
  • 我期望這兩個塊的組合返回'什麼給?',但它返回'測試'?
  • 我重寫Kernel.puts的方式對我來說似乎是一個永無止境的循環?

回答

0
module Capistrano 
    class Configuration 
    def puts string 
     ::Kernel.puts 'test' 
    end 
    def an_thing 
     puts "foo" 
    end 
    end 
end 

Capistrano::Configuration.new.an_thing 

給出的輸出:

test 

第二個版本也給出了相同的輸出。原因是你正在定義一個實例級別的方法而不是類級別的方法(this post似乎很好地解釋了這些差異)。稍微不同的版本:

module Kernel 
    def self.puts string 
    ::Kernel.puts 'what gives?' 
    end 
end 

會執行以下操作。因爲它會導致無限遞歸,就像您期望的那樣。

/tmp/foo.rb:14:in `puts': stack level too deep (SystemStackError) 
    from /tmp/foo.rb:14:in `puts' 
    from /tmp/foo.rb:4:in `puts' 
    from /tmp/foo.rb:7:in `an_thing' 
    from /tmp/foo.rb:18 

shell returned 1 
0

由於其編輯功能,我使用回答而不是評論。您可以對其進行編輯以添加更多信息,以後我可能會將其刪除。

現在當Capistrano來電時,我沒有看到「測試」,但我看到了 的原始輸出。

很難回答你的問題,而不知道卡皮斯特拉諾怎麼稱呼puts和哪一個。我會說這是正常的,如果投入顯示其參數,使用原來的Kernel#puts(它不清楚你所說的原始輸出,我必須假設你的意思是給予的字符串)。

  • 我希望第一個塊返回「測試」,但它沒有

我看到調用此類配置中定義的實例方法puts的唯一途徑模塊Capistrano的是:

Capistrano::Configuration.new.puts 'xxx' 

my_inst_var = Capistrano::Configuration.new 

和其他地方

my_inst_var.puts 'xxx' 

,當然它打印test。再一次,如果沒有看到其結果讓你感到意外的投票聲明,就不可能知道發生了什麼。

  • 我希望兩個塊的組合返回「怎麼辦?」,但它返回「測試」?

第二點是神祕的,我需要看到的代碼調用看跌期權,以及控制檯輸出。