当哈希内容发生变化时,我不想做某事。我对Hash
进行了细分,并像这样覆盖方法[]=
:
def []= (key,val)
super(key,val)
puts 'do something'
end
但是当我拨打merge
时,它无效。这样做的正确方法是什么?我是否必须覆盖更新哈希的每个方法?
答案 0 :(得分:2)
由于您不关心性能,您可以将冻结的哈希包装并委托给包装的冻结实例所有方法(抢救,报告和更新另一个副本。)在这里:
class MyHash < BasicObject
def initialize(hash = {})
hash! hash
end
def hash!(hash)
@hash = hash.freeze
end
def method_missing(m, *args, &λ)
hash.send(m, *args, &λ)
rescue => e
raise e unless e.message.ends_with?('frozen Hash')
# modification attempt was made
puts 'do something'
hash!(@hash.dup.send(m, *args, &λ)
end
end
未经测试,但你明白了。
答案 1 :(得分:0)
请记住返回访问的值,并覆盖merge
方法:
def []= (key,val)
out = super(key,val)
puts 'do something'
out
end
def merge(hash)
out = super
puts 'do something'
out
end
请考虑使用其他解决方案,因为moneky-patching核心类是一种可怕的做法,可能导致未定义的行为(如merge
方法失败)。
尝试使用继承:
class MyHash < Hash
def []= (key,val)
out = super(key,val)
puts 'do something'
out
end
def merge(hash)
out = super(hash)
puts 'do something'
out
end
end
# Usage
hash = MyHash.new
hash['a'] = 42 # prints 'do something'
要获得更优雅的解决方案,您可能需要查看hooks gem。