【问题标题】:Ruby overriding method from Trie gem - undefined method来自 Trie gem 的 Ruby 覆盖方法 - 未定义的方法
【发布时间】:2017-01-20 13:16:39
【问题描述】:

我在项目中使用 Trie (https://github.com/tyler/trie) gem 并且喜欢它。但它有一个非常令人讨厌的问题。

has_key? 方法在未找到密钥时返回 nil 而不是 false(因为每个以 ? 结尾的方法都应该)

我尝试在他们的 GitHub (https://github.com/tyler/trie/issues/26) 上打开一个问题,但没有成功。

所以,合理的下一步 - 尝试覆盖该方法。

我将此添加到我的项目中:

class Trie
    alias :old_has_key? :has_key?
    def has_key?(key)
        puts "My new Trie has_key"
        old_has_key?(key)
    end
end

只是看看我能不能摆脱它。

不幸的是,当我运行 rails console 时,我得到:

`<class:Trie>': undefined method `has_key?' for class `Trie' (NameError)

正如我在其他地方发现的那样,这应该可行。知道为什么没有吗?

我在这里缺少什么? trie.rb 的位置?还有什么?

【问题讨论】:

  • 最普遍接受的谓词方法定义(如has_key?)是它返回一个真值或假值。在大多数情况下,将 nil 作为虚假值返回就可以了。如果你在if trie.has_key?('whatever') 这样的条件下使用它,它的工作方式与返回false 一样。
  • 最明显的例子是defined? 运算符(虽然从技术上讲不是一个方法),它返回nil 表示未定义,否则返回一个描述定义的字符串。
  • 好吧,什么是正确的值得商榷,但即使是他们的文档也是错误的,因为他们说该方法返回 true/false 而它没有返回。我知道它在大多数情况下都有效,但是当您尝试将它与其他一些布尔值进行比较时它不起作用。我的问题仍然存在,为什么会出现这个错误,这让我感到困惑。
  • 文档确实没有完全反映现实。但是,现在的代码应该仍然可以使用。如果你真的需要真或假,你可以使用result = !!my_trie.has_key?('whatever')
  • 如果你想对一个 ruby​​ 对象使用布尔逻辑,只需直接使用该对象,而不是与nilfalse 比较。

标签: ruby-on-rails ruby trie


【解决方案1】:

从您的错误消息来看,您似乎在调用 has_key? 类的 has_key? 方法,而不是它的实例。如果您创建一个实例,您的代码就可以正常工作:

my_trie = Trie.new
my_trie.has_key?('foo')
# My new Trie has_key
# => nil

【讨论】:

  • 实际上当我尝试运行rails console 时出现错误。呼叫甚至没有被执行。让我编辑我的问题。
  • 再一次,只要您正确使用它,您的代码就可以工作。检查错误的轨迹。可能是对Trie.has_key?('whatever') 的调用在rails 启动期间执行并导致错误。
  • 事实证明,我不得不将我的trie.rb 移到更深的层次结构中。不太清楚为什么。
【解决方案2】:

所以我发现了问题。

我的新类嵌套在我的 Rails 应用程序中的 /lib 文件夹下。一旦我将它移至/lib/utils/,它就起作用了!

这意味着加载器在实际 Trie 类之前选择了我的自定义类。仍然不知道为什么。

【讨论】:

    【解决方案3】:

    你可以更简单地打补丁:

    class Trie
        def has_key?(key)
           !!super
        end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-07
      • 2013-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-06
      • 2012-12-14
      • 1970-01-01
      相关资源
      最近更新 更多