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

class A 
    include Test 
end 

A.model_method 

dies mit seinem Fehler:Warum 'Self' Methode des Moduls kann nicht eine Singleton Methode der Klasse werden?

nicht definierte Methode `model_method‘ für A: Klasse (NoMethodError)

Aber wenn ich metaclass von A. verwenden funktioniert es:

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

class A 
    class << self 
    include Test 
    end 
end 

A.model_method 

Kann jemand das erklären?

+1

möglich Duplikat [? Ist das möglich, eine Klassenmethode in einem Modul zu definieren] (http://stackoverflow.com/questions/4699355/is-that-possible-to-define -a-class-method-in-a-modul) –

Antwort

32

Wenn Sie beiden Klassenmethoden und Instanzmethoden in eine Klasse gemischt haben, wenn ein Modul einschließlich, können Sie das Muster folgen:

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 

Grundsätzlich zu über vereinfacht es, Sie extend Klasse Methoden hinzufügen und Sie include hinzufügen Instanzmethoden. Wenn ein Modul enthalten ist, wird #included Methode aufgerufen, mit der tatsächlichen Klasse, in der es enthalten war. Von hier aus können Sie die Klasse mit einigen Klassenmethoden aus einem anderen Modul extend. Dies ist ein ziemlich häufiges Muster.

Siehe auch: http://api.rubyonrails.org/classes/ActiveSupport/Concern.html

11

Das Einfügen eines Moduls ist analog zum Kopieren seiner Instanzmethoden.

In Ihrem Beispiel gibt es keine Instanzmethoden zum Kopieren nach A. model_method ist eigentlich eine Instanzmethode der Singleton-Klasse Test.


Gegeben:

module A 
    def method 
    end 
end 

Dieses:

module B 
    include A 
end 

ist analog dazu:

module B 
    def method 
    end 
end 

Wenn Sie es auf diese Art und Weise denken, dies macht Sinn:

module B 
    class << self 
    include A 
    end 
end 

B.method 

Hier werden die Methoden auf die Singleton Klasse B Modul kopiert werden, die ihnen die „Klassenmethoden“ von B macht.

Hinweis, dass dies genau das gleiche wie:

module B 
    extend A 
end 

In Wirklichkeit sind die Methoden nicht kopiert werden; gibt es keine Vervielfältigung. Das Modul wird einfach in die Methoden-Suchliste aufgenommen.

+1

Für Anfänger wie mich, diese Diskussion über den Unterschied zwischen erweitern und unter http: //www.railstips.org/blog/archives/2009/05/15/include-vs.-extend-in-ruby/war hilfreich, wenn es in Verbindung mit diesem Beitrag gelesen wurde. –

Verwandte Themen