通过mixin使操作员超载

问题描述

| 有没有一种方法可以通过在模块内部创建新的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/。     

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...