如何为ruby中的模块覆盖一个类?

时间:2014-03-26 18:58:48

标签: ruby oop syntax

为什么这不起作用?

module Magic
  class Fixnum
    def div2(other)
      self.to_f / other
    end

    alias :"/" :div2
  end
end

module SomeModule
  include Magic

  1/4 == 0.25 #should be true in here
end

1/4 == 0.25 #should be false everywhere else

3 个答案:

答案 0 :(得分:5)

您自己发布的答案实际上是全局更改Fixnum,这不是您想要的。也就是说,使用您的解决方案:

module Magic
  class ::Fixnum
    def div2(other)
      self.to_f / other
    end

    alias :"/" :div2
  end
end

# Yields 0.25 instead of expected 0. 
# This line should not be affected by your Fixnum change, but is.
1/4 

对于您描述的用例,Ruby 2.0引入了refinements,您可以使用如下所示。请注意,在Ruby 2.0中不能在另一个模块中使用using模块,但在Ruby 2.1中。因此,要使用Magic中的SomeModule模块,您将需要Ruby 2.1。如果您使用Windows,这可能是一个问题,因为您必须自己编译2.1,Windows二进制文件和安装程序仍然是2.0。

module Magic
  refine Fixnum do
    def /(other)
      self.to_f / other
    end
  end
end

1/4 # => 0
using Magic
1/4 # => 0.25

答案 1 :(得分:0)

好的,我需要访问顶级的Fixnum类,代码应为:

module Magic
  class ::Fixnum
    def div2(other)
      self.to_f / other
    end

    alias :"/" :div2
  end
end

这有效!

答案 2 :(得分:0)

如果您希望修改Fixnum仅适用于某些地方,可以使用refinements

module Magic
  refine Fixnum do
    def foo
      "Hello"
    end
  end
end

class SomeClass
  using Magic

  10.foo # => "Hello"

  def initialize
    10.foo # => "Hello"
  end
end

10.foo # Raises NoMethodError

您的原始示例在FixnumMagic)中定义了名为Magic::Fixnum类。它不会触及全球Fixnum。您在::Fixnum所说的位置发布的回复会修改全局Fixnum类。