2013-05-13 9 views
5

Newbie Frage:Kann ich Klassenmethoden und Instanzmethoden aus demselben Modul hinzufügen?

Ich weiß, wie einbeziehen und erweitern Arbeit, was ich frage mich ist, wenn es einen Weg gibt, um Klassen-und Instanz-Methoden von einem einzigen Modul zu bekommen?

Dies ist, wie ich es mit zwei Modulen:

module InstanceMethods 
    def mod1 
     "mod1" 
    end 
end 

module ClassMethods 
    def mod2 
     "mod2" 
    end 
end 

class Testing 
    include InstanceMethods 
    extend ClassMethods 
end 

t = Testing.new 
puts t.mod1 
puts Testing::mod2 

Vielen Dank für Ihre Zeit zu nehmen ...

Antwort

9

Es gibt ein gemeinsames Idiom dafür. Es verwendet included Objektmodell Haken. Dieser Haken wird jedes Mal aufgerufen, wenn ein Modul ein Modul/Klasse I ist

module MyExtensions 
    def self.included(base) 
    # base is our target class. Invoke `extend` on it and pass nested module with class methods. 
    base.extend ClassMethods 
    end 

    def mod1 
    "mod1" 
    end 

    module ClassMethods 
    def mod2 
     "mod2" 
    end 
    end 
end 

class Testing 
    include MyExtensions 
end 

t = Testing.new 
puts t.mod1 
puts Testing::mod2 
# >> mod1 
# >> mod2 

persönlich wie zum Beispiel Gruppen Methode auf eine verschachtelte Modul als auch. Aber das ist weniger akzeptiert, soweit ich weiß.

module MyExtensions 
    def self.included(base) 
    base.extend ClassMethods 
    base.include(InstanceMethods) 

    # or this, if you have an old ruby and the line above doesn't work 
    # base.send :include, InstanceMethods 
    end 

    module InstanceMethods 
    def mod1 
     "mod1" 
    end 
    end 

    module ClassMethods 
    def mod2 
     "mod2" 
    end 
    end 
end 
+0

Danke mir dies für Ausräumen. Löschen Sie eine beschreibende Information. Vielen Dank, dass Sie sich die Zeit genommen haben. –

+0

Siehe meine Antwort für eine ziemlich saubere Vereinfachung. :) – Magne

2
module Foo 
def self.included(m) 
    def m.show1 
    p "hi" 
    end 
end 

def show2 
    p "hello" 

end 
end 

class Bar 
include Foo 
end 

Bar.new.show2 #=> "hello" 
Bar.show1 #=> "hi" 
+0

Danke, dass du dir die Zeit genommen hast, Sergio hat die akzeptierte Antwort bekommen, wie er zuerst war. –

0

Ja. Es ist genau so einfach, wie man es erwarten würde, aufgrund der Genius des Rubins:

module Methods 
    def mod 
     "mod" 
    end 
end 

class Testing 
    include Methods # will add mod as an instance method 
    extend Methods # will add mod as a class method 
end 

t = Testing.new 
puts t.mod 
puts Testing::mod 

Oder könnten Sie tun:

module Methods 
    def mod1 
     "mod1" 
    end 

    def mod2 
     "mod2" 
    end 
end 

class Testing 
    include Methods # will add both mod1 and mod2 as instance methods 
    extend Methods # will add both mod1 and mod2 as class methods 
end 

t = Testing.new 
puts t.mod1 
puts Testing::mod2 
# But then you'd also get 
puts t.mod2 
puts Testing::mod1 
+0

Und wenn Sie einen Haken wie 'self.included' benötigen, können Sie auch' self.extended' verwenden. Siehe https://www.sitepoint.com/hitchhikers-guide-to-metaprogramming-classmodule-hooks/ – Magne

+0

Ich glaube nicht, dass Sie die Frage verstanden haben. :) Stellen Sie sich ein Modul/ein Problem vor, das zwei beabsichtigte Methodengruppen enthält: eine Instanzmethode und die andere Klasse [Instanzmethode]. Die Frage war: wie man beide (distinct!) Sätze von Methoden aus demselben Modul hinzufügt. –

+0

Ich weiß, das ist eine Möglichkeit, es zu interpretieren. Aber tbh, die Frage war nicht so klar, ob zwei verschiedene Methodensets benötigt würden (obwohl sein existierender Beispielcode es nötig machte). Das Schöne daran ist, dass ein Modul agnostisch sein kann, wie es verwendet wird. Sie müssen nicht voraussehen, wie die Methoden im Modul verwendet werden. Wenn Sie jedoch mehrere Methoden im Modul haben und sowohl ein Include als auch ein Extend ausgeführt haben, stehen Ihnen alle Methoden als Instanz- und Klassenmethoden zur Verfügung (nicht unterscheidbar). – Magne

Verwandte Themen