如何覆盖哈希本机括号([]访问权限)

时间:2014-11-23 16:04:20

标签: ruby hash override

我想覆盖ruby中的Hash类本机括号。

注意我不想在继承自Hash(没有子类化)的类中覆盖它们,我想实际上覆盖Hash本身,这样任何地方的任何哈希都会继承我的行为。

具体来说(奖励积分为......) - 我希望这能够原生地模仿具有无差别访问权限的哈希。在JavaScript中我会修改prototype,Ruby因其元编程而闻名,所以我希望这是可能的。

所以我的目标是:

>> # what do I do here to overload Hash's []?...
>> x = {a:123} # x is a native Hash
>> x[:a] # == 123, as usual
>> x['a'] # == 123, hooray!

我试过了: 1)

class Hash
  define_method(:[]) { |other| puts "Hi, "; puts other }
end

class Hash
  def []
    puts 'bar'
  end
end

两人都崩溃了。

3 个答案:

答案 0 :(得分:5)

这似乎完成了工作。

class Hash
  def [](key)
    value = (fetch key, nil) || (fetch key.to_s, nil) || (fetch key.to_sym, nil)     
  end

  def []=(key,val)
    if (key.is_a? String) || (key.is_a? Symbol) #clear if setting str/sym
        self.delete key.to_sym
        self.delete key.to_s        
    end
    merge!({key => val})
  end
end

现在:

user = {name: 'Joe', 'age' => 20} #literal hash with both symbols and strings as keys
user['name'] == 'Joe' # cool!
user[:age] == 20      # cool!

有关详细信息,请参阅:http://www.sellarafaeli.com/blog/ruby_monkeypatching_friendly_hashes

答案 1 :(得分:3)

class Hash
  def [] key
    value = fetch key rescue
    case key
    when Symbol then "#{value}, as usual"
    when String then "#{value}, hooray!"
    else value end
  end
end

答案 2 :(得分:0)

如果使用Rails HashWithIndifferentAccess已经支持此功能,即使使用Ruby,也可以权衡包括Active Support在内的功能。