问题描述
|
有没有一种方法可以通过在模块内部创建新的operator方法,然后将该模块混合到类中来覆盖类的运算符?
例如,这将覆盖Fixnum \的+运算符:
class Fixnum
def +(x)
product = x
product = product * self
return product
end
end
p 3 + 3
# => 9
这不会覆盖Fixnum \的+运算符:
module NewOperators
def +(x)
product = x
product = product * self
return product
end
end
class Fixnum
include NewOperators
end
p 3 + 3
# => 6
解决方法
您的问题使我想到了一篇有趣的文章,其中描述了该问题:
使用Metamorph修复Ruby的继承模型
我认为这是Ruby继承模型的最终问题。由于mixins的优先级始终比直接在类主体中定义的方法低,因此A#foo不能被mixin包含所覆盖。此外,由于混合优先级低于方法,因此A#foo现在违反了封装[...]
他的解决方案是在匿名内部模块内透明地定义所有新方法:
class Object
def self.method_added(name)
return if name == :initialize
const_set(:InstanceMethods,Module.new) unless defined?(self::InstanceMethods)
meth = instance_method(name)
self::InstanceMethods.send(:define_method,name) {|*args,&block| meth.bind(self).call(*args,&block) }
remove_method(name)
include self::InstanceMethods
end
end
这也方便地打包在一个名为metamorph的库中,该库使您可以通过只需要mixin方法来覆盖类方法。
, 不,因为在方法查找中,您只有在实际查看了当前类之后,才有机会引入在mixins或父类中定义的方法。
也就是说,您可以创建一个方法,该方法在类上调用时将在该类中创建方法。这可以让您轻松地将运算符注入类。
请注意,实际上这样做是使您惊讶的好方法。当您更改其他人依赖其行为的标准模块时,这是双重事实。有关上下文,请参见http://avdi.org/devblog/2008/02/23/why-monkeypatching-is-destroying-ruby/。