如何在Ruby中改进模块方法?

How to refine module method in Ruby?

你可以改进你的课程

1
2
3
4
5
6
7
module RefinedString
  refine String do
    def to_boolean(text)
    !!(text =~ /^(true|t|yes|y|1)$/i)
    end
  end
end

但如何细化模块方法?
这个:

1
2
3
4
5
6
7
module RefinedMath
  refine Math do
    def PI
      22/7
    end
  end
end

加注:TypeError: wrong argument type Module (expected Class)


这段代码将起作用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module Math
  def self.pi
    puts 'original method'
   end
end

module RefinementsInside
  refine Math.singleton_class do
    def pi
      puts 'refined method'
    end
  end
end

module Main
  using RefinementsInside
  Math.pi #=> refined method
end

Math.pi #=> original method

说明:

定义模块#method相当于在#singleton_class上定义实例方法。


Refinements only modify classes, not modules so the argument must be a class.

- http://ruby-doc.org/core-2.1.1/doc/syntax/refinements_rdoc.html

一旦您意识到自己在做什么,就有两种方法可以全局优化模块方法。 由于ruby具有开放类,您可以简单地覆盖该方法:

1
2
3
4
5
6
7
8
9
10
? Math.exp 2
#? 7.38905609893065
? module Math
?   def self.exp arg
?     Math::E ** arg
?   end  
? end  
#? :exp
? Math.exp 2
#? 7.3890560989306495

是否要保存要覆盖的方法的功能:

1
2
3
4
5
6
7
8
9
10
11
? module Math
?   class << self
?     alias_method :_____exp, :exp  
?     def exp arg  
?       _____exp arg    
?     end  
?   end  
? end  
#? Math
? Math.exp 2
#? 7.3890560989306495

请注意副作用。