【问题标题】:overloading an operator via a mixin通过 mixin 重载运算符
【发布时间】:2011-06-10 01:37:33
【问题描述】:

有没有办法通过在模块中创建新的操作符方法,然后将该模块混合到类中来覆盖类的操作符?

例如,这会覆盖 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

【问题讨论】:

标签: ruby


【解决方案1】:

您的问题使我看到了这篇描述问题的有趣文章:

Fixing Ruby’s Inheritance Model with Metamorph

在我看来,这是 Ruby 继承模型的终极问题。因为 mixin 的优先级总是低于直接在类主体中定义的方法,所以 A#foo 不能被 mixin 包含覆盖。此外,由于 mixins 的优先级低于方法,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 方法覆盖类方法。

【讨论】:

    【解决方案2】:

    不,因为在方法查找中,在您真正查看当前类之前,您没有机会提取在 mixins 或父类中定义的方法。

    也就是说,您可以创建一个方法,当在一个类上调用该方法时,该方法将在该类中创建方法。这可以让您轻松地将运算符注入到类中。

    请注意,实际上这样做是一个很好的惊喜秘诀。当您更改其行为被其他人依赖的标准模块时,这是双重事实。有关上下文,请参阅 http://avdi.org/devblog/2008/02/23/why-monkeypatching-is-destroying-ruby/

    【讨论】:

    • 有趣的文章!我可以看到猴子修补在大型项目中会如何失控。
    猜你喜欢
    • 2021-07-29
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    相关资源
    最近更新 更多