在模块中打开类

时间:2011-04-16 18:24:43

标签: ruby monkeypatching ruby-1.9.2

我知道我可以执行以下操作来向String类添加方法

class String
  def do_something
    puts self.size
  end
end

var = "test"
var.do_something

这将返回4

我希望能够拥有一个带有String的函数的模块,但是能够在这个字符串上调用do_something方法(例如见下文) - 是否可能?

编辑:添加了无效的示例代码

module TestModule
  class String
    def do_something
      puts self.size
    end
  end

  def self.test(str)    
    str.do_something
  end
end

这会出错:undefined method 'do_something' for "hello":String (NoMethodError)

2 个答案:

答案 0 :(得分:8)

编写代码的方式是定义一个名为TestModule :: String的新类。如果要修改内置的Ruby String类,如果要将声明保留在模块中,则需要使用String的完全限定名称(带“”::“)。

module TestModule
  class ::String
    def do_something
      puts self.size
    end
  end

  def self.test(str)  
    str.do_something
  end
end

添加“::”告诉Ruby你想要的String类不是TestModule的一部分。

在同一个文件中声明TestModule之外的String可能更简洁。

如果您不想污染全局String类,则只需修改要将方法添加到的特定String实例。

module TestModule
  def self.test(str)  
    do_somethingify!(str)
    str.do_something
  end

  def self.do_somethingify!(str)
    unless str.respond_to? :do_something
      str.instance_eval do
        def do_something
          puts size
        end
      end
    end
  end      
end          

答案 1 :(得分:3)

也许这个?

module TestModule
  module_function
  def test(str)
    str.instance_eval{doSomething}
  end
end

Test.test(str)

修改由于问题更改而更改

只需将doSomething的定义放在TestModule类之外。

class String
  def doSomething
    puts size
  end
end

module TestModule
  module_function
  def test(str)  
    str.doSomething
  end
end