代码之家  ›  专栏  ›  技术社区  ›  Sniggerfardimungus

在没有继承的情况下,如何重写类方法并从新方法中调用原始方法?

  •  9
  • Sniggerfardimungus  · 技术社区  · 16 年前

    Time.strftime 这样地:

    class Time
      alias :old_strftime :strftime
      def strftime
        #do something
        old_strftime
      end
    end
    

    问题是, strftime 是一个实例方法。我需要重写 Time.now -一个类方法——任何调用方都可以得到我的新方法,而新方法仍然调用原始方法 .now 方法我看过 alias_method 没有成功。

    4 回复  |  直到 16 年前
        1
  •  12
  •   Cameron Price    16 年前

    这有时很难理解,但需要打开“特征类”,它是与特定类对象关联的单例。该类的语法为<&书信电报;自我完成…结束。

    class Time
      alias :old_strftime :strftime
    
      def strftime
        puts "got here"
        old_strftime
      end
    end
    
    class Time
      class << self
        alias :old_now :now
        def now
          puts "got here too"
          old_now
        end
      end
    end
    
    t = Time.now
    puts t.strftime
    
        2
  •  2
  •   Austin Ziegler    16 年前

    class Time
      class << self
        alias_method :old_time_now, :now
    
        def now
          my_now = old_time_now
          # new code
          my_now
        end
      end
    end
    
    class << Time
      alias_method :old_time_now, :now
    
      def now
        my_now = old_time_now
        # new code
        my_now
      end
    end
    
        3
  •  1
  •   Avdi    16 年前

    如果您需要为测试目的重写它(这是我通常想要重写Time.now的原因),Ruby mocking/Stubing框架将很容易为您做到这一点。例如,使用RSpec(使用flexmock):

    Time.stub!(:now).and_return(Time.mktime(1970,1,1))
    

    class Foo
      def initialize(clock=Time)
        @clock = clock
      end
    
      def do_something
        time = @clock.now
        # ...
      end
    end
    
        4
  •  0
  •   Federico Ramallo    14 年前

    我一直在试图找出如何使用模块重写实例方法。

    module Mo
      def self.included(base)
        base.instance_eval do
          alias :old_time_now :now
          def now
            my_now = old_time_now
            puts 'overrided now'
            # new code
            my_now
          end
        end
      end
    end
    Time.send(:include, Mo) unless Time.include?(Mo)
    
    > Time.now
    overrided now
    => Mon Aug 02 23:12:31 -0500 2010