Ruby 向命名空间中的字符串添加方法
我正在Ruby 向命名空间中的字符串添加方法,ruby,metaprogramming,Ruby,Metaprogramming,我正在String上定义一些新方法。我需要确保这些方法不会与其他库中定义的方法冲突(作为参考,我创建了一个屈折因子,然后在字符串上添加了pluralize和singularize) 我的第一个想法是将新内容包装在一个模块中,如下所示: module MM class String def rev self.split('').reverse.join('') end end end class Test include MM def me(s)
String
上定义一些新方法。我需要确保这些方法不会与其他库中定义的方法冲突(作为参考,我创建了一个屈折因子,然后在字符串上添加了pluralize
和singularize
)
我的第一个想法是将新内容包装在一个模块中,如下所示:
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')
但这当然行不通<代码>字符串#版本
保持未定义状态。我的代码中真正包含的是一个模块MM
,除了内置的类型扩展之外,所有内容都包装在MM
中。我的目标是让String
具有类似rev
、单数化
和复数化
的方法,但仅在该模块内,MM
这似乎应该是可行的。但不知何故,我错过了秘密咒语,这将使它如此
如果有人能提供一些建议,我们将不胜感激。还有另一种方法可以让字符串类保持分离。在你添加需求之前,它将是免费的
#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')
还有另一种方法可以将字符串类分开。在你添加需求之前,它将是免费的
#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')
你在寻找“改进”。它们是Ruby 2.0中的一个实验性特性,因此如果不使用2.0,您可能会运气不佳。我自己还没有使用过它们,但您的示例几乎就是改进的规范用例。使用refine
和using
关键字获得所需的行为:
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')
你在寻找“改进”。它们是Ruby 2.0中的一个实验性特性,因此如果不使用2.0,您可能会运气不佳。我自己还没有使用过它们,但您的示例几乎就是改进的规范用例。使用refine
和using
关键字获得所需的行为:
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')
如果没有细化,可以扩展单个字符串对象:
module StringHelper
def rev
self.split('').reverse.join('')
end
end
class Test
def me(s)
s.extend(StringHelper).rev
end
end
或子类字符串:
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
class-StringPlus
缺少细化,您可以扩展单个字符串对象:
module StringHelper
def rev
self.split('').reverse.join('')
end
end
class Test
def me(s)
s.extend(StringHelper).rev
end
end
或子类字符串:
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
class-StringPlus
作为一种在没有改进的情况下的解决方法,我发现这种方法是有效的:
# 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
的早期定义,则将遵循该定义,而不会覆盖该定义。这有点老套,取决于文件加载的顺序,但如果加载顺序受到控制,它确实会起作用。在没有改进的情况下,作为一种解决方法,我发现这类事情是有效的:
# 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
的早期定义,则将遵循该定义,而不会覆盖该定义。这有点老套,取决于文件加载的顺序,但如果加载顺序得到控制,它确实会起作用。我不完全确定我是否理解;您只想在您自己的类中扩展字符串?只想在我自己的模块中扩展字符串。我只需要避免这些影响到其他实现,反之亦然。我知道我可以重命名它们来解决这个问题,但这似乎是名称空间的设计目的;在类中动态定义/取消定义方法有些不同。如果您想在模块中定义方法并将它们放入字符串中,这与仅在特定范围内提供这些方法不同。我认为Ruby 2.0引入了一些新的monkey补丁功能,这些功能(可能)有助于解决这些问题。在Ruby 2.0下,您只能将monkey补丁放在全局空间中,这将影响所有类别(不符合您的要求);在ruby 2.0中,您可以使用下面答案中显示的细化
,这是您唯一的选择,但我不能完全理解;您只想在您自己的类中扩展字符串?只想在我自己的模块中扩展字符串。我只需要避免这些影响到其他实现,反之亦然。我知道我可以重命名它们来解决这个问题,但这似乎是名称空间的设计目的;在类中动态定义/取消定义方法有些不同。如果您想在模块中定义方法并将它们放入字符串中,这与仅在特定范围内提供这些方法不同。我认为Ruby 2.0引入了一些新的monkey补丁功能,这些功能(可能)有助于解决这些问题。在Ruby 2.0下,您只能将monkey补丁放在全局空间中,这将影响所有类别(不符合您的要求);在ruby 2.0中,您可以使用下面答案中显示的细化
,这是您唯一的选择为“这是一个测试”给出命名方法错误:未定义的方法“rev”:String
这是因为rev
没有被添加到String
的方法中。方法“m”之所以有效,是因为它只是类Test
上的一个实例方法。我希望s.rev
起作用。givesNoMethodError:this is test的未定义方法'rev':String
这是因为rev
没有添加到String
的方法中。方法“m”之所以有效,是因为它只是类Test
上的一个实例方法。我想要s.rev
工作。顺便说一句:这不行。我只是在几分钟前才发现这一点,当时我正在写你上面写的内容;-)它直到最近才开始工作,但在2.0.0-p0发布前不久,改进规范发生了变化。特别是,using
被定义为顶级main
对象的私有单例方法,这意味着它仅在顶级范围内可用。因此,优化总是应用于整个文件和所有模块