在命名空间中向字符串添加方法

时间:2013-03-05 22:14:55

标签: ruby metaprogramming

我在String上定义了一些新方法。我需要确保这些方法不与其他库中定义的方法冲突(作为参考,我创建了一个变形器,然后将pluralizesingularize添加到String)。

我的第一个想法是将新东西包装在一个模块中:

module MM
  class String
    def rev
      self.split('').reverse.join('')
    end
  end
end

class Test
  include MM

  def me(s)
    s.rev
  end
end

puts Test.new.me('this is a test')

但当然这不起作用。 String#rev仍未定义。我在代码中真正拥有的是模块MM,除了内置类型扩展之外的所有内容都包含在MM中。我的目标是让String拥有revsingularizepluralize等方法,但仅限于该模块MM内。

这似乎应该是可行的。但不知怎的,我错过了秘密咒语,这将使它如此。

如果有人能提出一些建议,我们将不胜感激。

4 个答案:

答案 0 :(得分:2)

您正在寻找“改进”。它们是Ruby 2.0中的一个实验性功能,所以如果你不使用2.0,你可能会失败。我自己还没有使用过它们,但是你的例子几乎就是改进的规范用例。使用refineusing关键字获取您想要的行为:

module MM
  refine class String
    def rev
      self.split('').reverse.join('')
    end
  end
end

class Test
  using MM

  def me(s)
    s.rev
  end
end

puts Test.new.me('this is a test')

答案 1 :(得分:2)

缺乏优化,您可以扩展单个字符串对象:

module StringHelper
  def rev
    self.split('').reverse.join('')
  end
end

class Test
  def me(s)
    s.extend(StringHelper).rev
  end
end

或子类String:

class StringPlus < String
  def rev
    self.split('').reverse.join('')
  end
  def self.[](s)
    new(s)
  end
end

class Test
  def me(s)
    StringPlus[s].rev
  end
end

答案 2 :(得分:0)

还有另一种方法可以让你的字符串类分开。在你添加require之前,它将免于一切。

#my_string.rb
class String
  def rev
      self.split('').reverse.join('')
   end
end

#test.rb
class Test
  require 'F:\on going\New Site\Ruby\my_string.rb' # Assuming both these files are in the same folder


  def me(s)
    s.rev
  end
end


puts Test.new.me('this is a test')

答案 3 :(得分:0)

作为一种没有改进的解决方法,我发现这种方法有效:

# class String
#   def rev
#     puts "rev: #{self}"
#   end
# end

class String
  unless String.instance_methods.include?(:rev)
    def rev
      self.split('').reverse.join('')
    end
  end
end

class Test
  def me(s)
    s.rev
  end
end

puts Test.new.me('this is a test')

如果您取消注释rev的早期定义,它将被尊重而不会被覆盖。这有点hacky并且依赖于文件加载的顺序,但是如果加载顺序是受控的,它确实有效。