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

时间:2023-01-15 18:56:14

You can refine your class with

你可以改进你的课程

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

but how to refine module method? This:

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

module RefinedMath
  refine Math do
    def PI
      22/7
    end
  end
end

raises: TypeError: wrong argument type Module (expected Class)

引发:TypeError:错误的参数类型Module(期望的Class)

2 个解决方案

#1


11  

This piece of code will work:

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

Explanation:

Defining a module #method is equivalent to defining an instance method on its #singleton_class.

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

#2


1  

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

As soon as you are aware of what you are doing, you have two options to refine module methods globally. Since ruby has open classes, you might simply override the method:

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

▶ Math.exp 2
#⇒ 7.38905609893065
▶ module Math
▷   def self.exp arg
▷     Math::E ** arg
▷   end  
▷ end  
#⇒ :exp
▶ Math.exp 2
#⇒ 7.3890560989306495

Whether you want to save the functionality of the method to be overwritten:

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

▶ module Math
▷   class << self
▷     alias_method :_____exp, :exp  
▷     def exp arg  
▷       _____exp arg    
▷     end  
▷   end  
▷ end  
#⇒ Math
▶ Math.exp 2
#⇒ 7.3890560989306495

Please be aware of side effects.

请注意副作用。

#1


11  

This piece of code will work:

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

Explanation:

Defining a module #method is equivalent to defining an instance method on its #singleton_class.

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

#2


1  

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

As soon as you are aware of what you are doing, you have two options to refine module methods globally. Since ruby has open classes, you might simply override the method:

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

▶ Math.exp 2
#⇒ 7.38905609893065
▶ module Math
▷   def self.exp arg
▷     Math::E ** arg
▷   end  
▷ end  
#⇒ :exp
▶ Math.exp 2
#⇒ 7.3890560989306495

Whether you want to save the functionality of the method to be overwritten:

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

▶ module Math
▷   class << self
▷     alias_method :_____exp, :exp  
▷     def exp arg  
▷       _____exp arg    
▷     end  
▷   end  
▷ end  
#⇒ Math
▶ Math.exp 2
#⇒ 7.3890560989306495

Please be aware of side effects.

请注意副作用。