كيف يمكن للمرء - دون الميراث - تجاوز أسلوب فئة واستدعاء الأصلي من داخل الأسلوب الجديد؟

StackOverflow https://stackoverflow.com/questions/288020

سؤال

ولقد وجدت مصدر واحد التي Time.strftime تجاهلت بنجاح مثل هذا:

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

والمشكلة هي، strftime هو أسلوب مثيل. ولست بحاجة لتجاوز Time.now - طريقة الطبقة - في مثل هذا بعيدا أن أي المتصل يحصل لي طريقة جديدة، في حين أن الأسلوب الجديد لا يزال باستدعاء أسلوب .now الأصلي. لقد ألقيت نظرة على alias_method وقد التقى مع أي نجاح.

هل كانت مفيدة؟

المحلول

وهذا من الصعب نوعا ما للحصول على رأسك حول بعض الأحيان، ولكن تحتاج لفتح "eigenclass" وهو المفرد المرتبطة كائن فئة محددة. بناء الجملة من أجل هذه هي الدرجة << النفس تفعل ... نهاية.

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

نصائح أخرى

وأساليب وطرق الدرجة فقط. أنا أوصي ضد هذا، ولكن لديك خياران أي ما يعادل:

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

وإذا كانت تحتاج إلى تجاوز ذلك لأغراض الاختبار (السبب أريد عادة لتجاوز Time.now)، روبي ساخرا / والأطر الإستئصال القيام بذلك نيابة عنك بسهولة. على سبيل المثال، مع 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

ولقد تم في محاولة لمعرفة كيفية تجاوز أسلوب مثيل استخدام وحدات.

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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top