6

クラスA、B、Cがあるとしましょう。

A
 def self.inherited(sub)
   # meta programming goes here
   # take class that has just inherited class A
   # and for foo classes inject prepare_foo() as 
   # first line of method then run rest of the code
 end

 def prepare_foo
   # => prepare_foo() needed here
   # some code
 end

end

B < A
  def foo
    # some code
  end
end

C < A
  def foo
    # => prepare_foo() needed here
    # some code
  end
end

ご覧のとおり、私はfoo_prepare()foo()メソッドに呼び出しを挿入しようとしています。

どうすればそれができますか?

sendまた、私は、クラスをオーバーライドしclass Aて実行し、メソッドの残りの部分を(スーパー)に実行foo_prepareさせることを考えていました。send

あなたたちはどう思いますか、この問題に取り組むための最良の方法は何ですか?

4

3 に答える 3

8

これがあなたのための解決策です。これはモジュール インクルージョンに基づいており、クラスからの継承ではありませんが、それでも役に立つことを願っています。

module Parent
  def self.included(child)
    child.class_eval do
      def prepare_for_work
        puts "preparing to do some work"
      end
  
      # back up method's name
      alias_method :old_work, :work
  
      # replace the old method with a new version, which has 'prepare' injected
      def work
        prepare_for_work
        old_work
      end
    end
  end
end

class FirstChild
  def work
    puts "doing some work"
  end

  include Parent # include in the end of class, so that work method is already defined.
end

fc = FirstChild.new
fc.work
# >> preparing to do some work
# >> doing some work
于 2012-09-20T10:37:47.320 に答える
4

Sergioのソリューションをお勧めします(受け入れられたとおり)。これが私のニーズに合ったものです。

class A
  def send(symbol,*args)
    # use array in case you want to extend method covrage
    prepare_foo() if [:foo].include? symbol
    __send__(symbol,*args)
  end
end

また

class A
  alias_method :super_send, :send           

  def send(symbol,*args)
    prepare_foo() if [:foo].include? symbol
    super_send(symbol,*args)
  end
end
于 2012-09-20T10:57:09.480 に答える
2

Ruby 2.0 では、'prepend' を使用して Sergio のソリューションを単純化できます。

module Parent
  def work
    puts "preparing to do some work"
    super
  end
end

class FirstChild
  prepend Parent

  def work
    puts "doing some work"
  end
end

fc = FirstChild.new
fc.work

これにより、モジュールは alias_method を必要とせずにクラスのメソッドをオーバーライドできます。

于 2014-10-27T14:55:49.500 に答える