2013-05-13 21 views
5

Pytanie dla nowicjusza:Czy mogę dodać metody klas i metody instancji z tego samego modułu?

Wiem, jak zawrzeć i rozszerzyć zakres pracy, zastanawiam się, czy istnieje sposób na uzyskanie metod klas i instancji z jednego modułu?

To jak to zrobić z dwóch modułów:

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 

Dzięki za poświęcenie czasu ...

Odpowiedz

9

Istnieje wspólny idiom za to. Korzysta z haka modelu obiektowego included. Hak ten zostanie wywołany za każdym razem, gdy moduł jest włączony do modułu/klasy

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 

ja osobiście jak do grupy metody instancji do modułu zagnieżdżonego, jak również. Jest to jednak mniej akceptowana praktyka, o ile wiem.

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

Dziękuję za wyjaśnienie tego do mnie. Wyczyść opisową informację. Dziękuję bardzo za poświęcenie czasu. –

+0

Zobacz moją odpowiedź na dość schludne uproszczenie tego. :) – 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

Dzięki za poświęcenie czasu, Sergio otrzymał zaakceptowaną odpowiedź, jak był pierwszy. –

0

Tak. To jest dokładnie tak proste, jak można się spodziewać, z powodu geniuszu rubin:

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 

Albo można zrobić:

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

A jeśli potrzebujesz haka typu 'self.included', możesz również użyć' self.extended'. Zobacz https://www.sitepoint.com/hitchhikers-guide-to-metaprogramming-classmodule-hooks/ – Magne

+0

Nie sądzę, że rozumiesz to pytanie. :) Wyobraźmy sobie moduł/zagadnienie, które przenosi dwa zamierzone zestawy metod: jeden do metod instancji, a drugi - do metod klasy [instancja]. Pytanie brzmiało: jak dodać oba (różne!) Zestawy metod z tego samego modułu. –

+0

Rozumiem, że to jeden ze sposobów na zinterpretowanie tego. Ale tbh, pytanie nie było jednoznaczne z potrzebą dwóch różnych zestawów metod (chociaż jego istniejący przykładowy kod wymagał tego). Piękno tego jest takie, że moduł może być agnostyczny, jeśli chodzi o sposób jego użycia. Nie musisz przewidywać, w jaki sposób zostaną użyte metody w module. Jeśli jednak masz wiele metod w module i wykonałeś zarówno rozszerzenie, jak i rozszerzenie, wszystkie metody będą dostępne zarówno jako metody instancji, jak i klasy (nierozróżnialne). – Magne

Powiązane problemy