override namespaced puts仅在重写Kernel.puts后有效吗?

时间:2012-12-31 22:40:01

标签: ruby override 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实际上返回“test”,而不是“what give?”,而不是原始内容,而是“test”。

是否有合理的解释为什么会发生这种情况(除了我对Ruby Kernel内部工作的有限理解之外)?

向我看的东西(但不知何故“似乎有用”):

  • 我希望第一个块返回'test',但它没有
  • 我希望两个块的组合能够返回'what give?',但它会返回'test'?
  • 我覆盖Kernel.puts的方式对我来说似乎是一个永无止境的循环?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

由于其编辑功能,我使用的是答案而不是评论。您可以对其进行编辑以添加更多信息,我可以稍后将其删除。

  

现在当卡皮斯特拉诺打电话给我时,我看不到“测试”,但我看到了   原始输出。

如果没有看到卡皮斯特拉诺如何称呼puts以及哪一个问题,就很难回答你的问题。我会说如果puts使用原始Kernel#puts显示其参数是正常的(不清楚你所谓的原始输出,我必须假设你的意思是赋予put的字符串)。

  
      
  • 我希望第一个块返回'test',但它没有
  •   

我看到调用Capistrano模块中的类Configuration中定义的实例方法puts的唯一方法是:

Capistrano::Configuration.new.puts 'xxx'

my_inst_var = Capistrano::Configuration.new

和其他地方

my_inst_var.puts 'xxx'

当然会打印test。再一次,如果没有看到结果令你惊讶的puts语句,就不可能知道发生了什么。

  
      
  • 我希望两个块的组合能够返回'what give?',但它会返回'test'?
  •   

第二点是神秘的,我需要看到代码调用puts,以及控制台输出。