【问题标题】:override namespaced puts only works after overriding Kernel.puts?覆盖命名空间的 put 仅在覆盖 Kernel.puts 后才有效?
【发布时间】:2012-12-31 22:40:00
【问题描述】:

抱歉问题标题含糊不清,但我不知道是什么原因导致以下问题:

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 内核的内部工作原理的有限理解)?

对我来说不合适的事情(但不知何故“似乎有效”):

  • 我希望第一个块返回“测试”,但它没有
  • 我希望这两个块的组合返回“what give?”,但它返回“test”?
  • 我重写 Kernel.puts 的方式对我来说似乎是一个永无止境的循环?

【问题讨论】:

    标签: ruby overriding puts


    【解决方案1】:
    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
    

    【讨论】:

      【解决方案2】:

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

      现在当 Capistrano 调用 put 时,我看不到“test”,但我看到了 原始输出。

      如果不了解 Capistrano 是如何调用puts 以及是哪一个,就很难回答您的问题。如果 puts 显示它的参数,我会说这是正常的,使用原始的 Kernel#puts(不清楚你所说的 original output,我必须假设你的意思是给 puts 的字符串)。

      • 我希望第一个块返回“测试”,但它没有

      我看到调用 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的代码,以及控制台输出。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-08
        • 1970-01-01
        • 2020-07-03
        • 1970-01-01
        • 2021-06-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多