2012-04-06 10 views
15
module Test 
    def self.model_method 
    puts "this is a module method" 
    end 
end 

class A 
    include Test 
end 

A.model_method 

と、このなりますエラー:モジュールの '自己'メソッドがなぜクラスのシングルトンメソッドになれないのですか?

未定義のメソッドのための `model_method」:クラス(NoMethodError)

しかし、私はAのメタクラスを使用した場合、それは動作します:

module Test 
    def model_method 
    puts "this is a module method" 
    end 
end 

class A 
    class << self 
    include Test 
    end 
end 

A.model_method 

誰かがこれを説明できますか?

+1

が重複する可能性が[?モジュールでクラスメソッドを定義することは可能です](http://stackoverflow.com/questions/4699355/is-that-possible-to-define -a-class-method-in-a-module) –

答えて

32

あなたはモジュールを含むクラスに混入し、両方のクラスメソッドとインスタンスメソッドを持っているしたい場合は、パターンに従うことがあります。

module YourModule 
    module ClassMethods 
    def a_class_method 
     puts "I'm a class method" 
    end 
    end 

    def an_instance_method 
    puts "I'm an instance method" 
    end 

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

class Whatever 
    include YourModule 
end 

Whatever.a_class_method 
# => I'm a class method 

Whatever.new.an_instance_method 
# => I'm an instance method 

基本的にオーバー簡素化し、それをするには、extendクラスメソッドを追加しますインスタンスメソッドを追加するにはincludeです。モジュールが含まれている場合は、#includedメソッドが呼び出され、実際のクラスが含まれています。extend他のモジュールのクラスメソッドを持つクラスをここから取得できます。これはかなり共通のパターンです。

も参照してください:http://api.rubyonrails.org/classes/ActiveSupport/Concern.html

11

モジュールを含めることは、そのインスタンスメソッドをコピーすることに似ています。

例では、Aにコピーするインスタンスメソッドはありません。 model_methodは実際にはTestのシングルトンクラスのインスタンスメソッドです。


は考える:

module A 
    def method 
    end 
end 

この:

module B 
    include A 
end 

はこれに似ています。

module B 
    def method 
    end 
end 

あなたはそれをこのように考えると、これは完璧な理にかなっています:

module B 
    class << self 
    include A 
    end 
end 

B.method 

ここでは、メソッドはBモジュールのシングルトンクラスにコピーされ、Bの「クラスメソッド」になります。これはとまったく同じものであることを

注:

現実に
module B 
    extend A 
end 

、メソッドがコピーされていません。 の重複はありません。このモジュールは単にメソッドルックアップリストに含まれています。

+1

私のような初心者の方には、http://www.railstips。org/blog/archives/2009/05/15/include-vs-extend-in-ruby /は、この投稿と併せて読むと参考になりました。 –

関連する問題