安全地扩展标准库类

时间:2016-11-09 11:53:59

标签: ruby

是否有一种简单的方法可以在模块中扩展标准库类(如String)的功能而不会影响其外部的任何内容?示例(不起作用):

module Foo
  class String
    def hello
      "hello #{self}!"
    end
  end

  class Bar
    def greet name
      name.hello
    end
  end
end

结果我正在寻找:

Foo::Bar.new.greet 'Tom' #=> hello Tom!
'Tom'.hello #=> NoMethodError

我知道创建具有所需功能的MyString < String等解决方案,但每次我想在模块中使用字符串时,我宁愿不调用MyString.new('foo')

我意识到这可能不是一种好习惯,我只是想扩大对语言的理解。

2 个答案:

答案 0 :(得分:3)

您要找的是Refinement

  

改进旨在减少猴子修补的影响   猴子修补课程的其他用户。 优化提供了一种方法   在本地扩展一个类

module Foo
  refine String do
    def hello
      "hello #{self}!"
    end
  end
end

puts 'Tom'.hello
#=> undefined method `hello' for "Tom":String
using Foo
puts 'Tom'.hello
#=> hello Tom!

Bar类中使用细化:

# Without refinement
class Bar
  def greet(name)
    name.hello
  end
end

puts Bar.new.greet('Tom')
#=> undefined method `hello' for "Tom":String

# With refinement
class Bar
  using Foo
  def greet(name)
    name.hello
  end
end

puts Bar.new.greet('Tom')
#=> hello Tom!

有关范围界定,方法查找和内容的完整信息,请查看我提供的文档链接:)

P.S。请注意,Rubinius开发人员在哲学上反对精炼,因此永远不会实施它们(c)JörgWMittag。

答案 1 :(得分:0)

写一个同名的类,然后使用require_relative(或类似方法)将其包括在内。

class Date
    def itis
        puts "It is " + self.to_s
    end

示例:

[1] pry(main)> require_relative 'date.rb'
=> true
[2] pry(main)> require 'date'
=> true
[3] pry(main)> Date.new(2018, 10, 9).itis
It is 2018-10-09
=> nil