2015-08-20 25 views
7

Sie können Ihre Klasse mitWie verfeinern Sie die Modulmethode in Ruby?

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

aber wie verfeinern Modul-Methode verfeinern? Dies:

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

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

Antwort

1

Ergebnis nur Klassen ändern, keine Module so das Argument eine Klasse sein muss.

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

Sobald Sie wissen, was Sie tun, haben Sie zwei Möglichkeiten zu refine Modul Methoden global. Da Rubin offene Klassen hat, können Sie einfach die Methode überschreiben:

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

Ob die Funktionalität der Methode gespeichert werden soll überschrieben werden:

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

Bitte von Nebenwirkungen bewusst.

+1

So ist es eine Möglichkeit, Modul-Methode _refine_? –

+0

Momentan gibt es keine Möglichkeit, Module zu verfeinern, wie es in der Dokumentation, die ich verlinkt habe, deutlich gemacht wurde. – mudasobwa

+0

Es könnte andere Lösung als die Verwendung genau 'verfeinern' Methode und das ist, was ich suche –

8

Nun, da ein Modul #method ist equivalent eine Instanz-Methode auf seine #singleton_class zu definieren, folgendes funktioniert:

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