Как можно - без наследования - переопределить метод класса и вызвать оригинал из нового метода? - PullRequest
9 голосов
/ 13 ноября 2008

Я нашел один источник, который успешно переопределил Time.strftime, например:

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

Проблема в том, что strftime - это метод экземпляра. Мне нужно переопределить Time.now - метод класса - таким образом, чтобы любой вызывающий получил мой новый метод, в то время как новый метод все еще вызывает оригинальный метод .now. Я посмотрел на alias_method и не добился успеха.

Ответы [ 4 ]

12 голосов
/ 13 ноября 2008

Иногда довольно сложно разобраться, но вам нужно открыть «собственный класс», который является синглтоном, связанным с конкретным объектом класса. синтаксис для этого класса << self do ... end. </p>

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 голосов
/ 13 ноября 2008

Методы класса - это просто методы. Я настоятельно рекомендую против этого, но у вас есть два эквивалентных варианта:

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
1 голос
/ 13 ноября 2008

Если вам нужно переопределить его для целей тестирования (причина, по которой я обычно хочу переопределить Time.now), среды Ruby mocking / stubbing помогут вам легко. Например, с RSpec (который использует flexmock):

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

Кстати, я настоятельно рекомендую избегать необходимости заглушать Time.now, предоставляя вашим классам переопределяемые часы:

class Foo
  def initialize(clock=Time)
    @clock = clock
  end

  def do_something
    time = @clock.now
    # ...
  end
end
0 голосов
/ 03 августа 2010

Я пытался выяснить, как переопределить метод экземпляра с помощью модулей.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...