2

Rubyでは、次のことができます。

module Foo
end

class Bar
  include Foo
end

module Foo
  def do_something_instancey
    puts "I'm an instance!"
  end
end

次に、Barオブジェクトをインスタンス化すると、それを呼び出すことができますdo_something_instancey

b = Bar.new
b.do_something_instancey

しかし、私がこれを行うと...

module Foo
  def self.included(base)
    def base.do_something_classy do
      puts "I'm a class!"
    end
  end
end

私の理解では、そのクラスメソッドを定義する前に含めたため、に「アタッチ」されなかったため、呼び出すFooことBar Bar.do_something_classyできませんBar

私はそれが少し不正確かもしれない/本当に正しい用語ではないかもしれないことを理解しています。とにかく、上記の例で、モジュールがすでに含まれている後にクラスメソッドをBarfromにアタッチする方法はありますか?Foo

4

2 に答える 2

2

クラスメソッドとインスタンスメソッドの両方の例を次に示します。

module Foo
  def self.included(base)
    base.extend(ClassMethods)
  end

   module ClassMethods
   end
end

class Bar
  include Foo
end

module Foo
  def do_something_instancey
    puts "I'm an instance!"
  end

  module ClassMethods
    def do_something_classy
      puts "I'm a class!"
    end
  end
end

b = Bar.new
b.do_something_instancey
# => I'm an instance!
Bar.do_something_classy
# => I'm a class!

ObjectSpace特定のモジュールが(すでに)含まれている各クラスにクラスメソッドを追加するには、Rubyの:をトラバースできます。

ObjectSpace.each_object(Class) do |klass|
  if klass.include? Foo
    klass.define_singleton_method(:do_something_classy) do
      puts "I'm a class!"
    end
  end
end
于 2012-07-24T15:58:20.927 に答える
1

retroactive_module_inclusion gemの説明:

このgemは、「動的モジュールインクルード」(別名「ダブルインクルージョン」)の問題を回避します。これは、M.module_eval {include N}が、モジュールMを事前にインクルードしていたモジュールおよびクラスがモジュールNのメソッドを使用できるようにしないという事実です。その後それを含むものにのみ。特にKがクラスの場合、K.class_eval {include M}、以前に継承したすべてのクラスでMのすべてのメソッドを使用できるようにするため、この動作は驚き最小の原則を損ないます。

于 2014-03-31T21:23:24.457 に答える