2010-07-01 8 views
5

W tym kodzie Ruby:Czy jest możliwe aby wywołać funkcję modułu od wewnątrz klasy, która jest również w tym module

Module M 
    Class C < Struct.new(:param) 
    def work 
     M::helper(param) 
    end 
    end 

    def helper(param) 
    puts "hello #{param}" 
    end 
end 

dostaję „metoda niezdefiniowany«pomocnika»dla«M: Moduł»” błąd gdy próbuję uruchomić , ale wywołanie M::helper("world") bezpośrednio z innej klasy działa poprawnie. Czy klasy nie mogą wywoływać funkcji modułu, które są zdefiniowane w tym samym module, w którym są zdefiniowane? Czy jest jakiś sposób obejścia tego poza przenoszeniem klasy poza moduł?

Odpowiedz

4

Aby skorzystać M::helper trzeba zdefiniować go jako def self.helper; end Dla celów porównawczych, przyjrzeć pomocnika i helper2 w kolejnym zmodyfikowanym fragmentem

module M 
    class C < Struct.new(:param) 
    include M  # include module to get helper2 mixed in 
    def work 
     M::helper(param) 
     helper2(param) 
    end 
    end 

    def self.helper(param) 
    puts "hello #{param}" 
    end 

    def helper2(param) 
    puts "Mixed in hello #{param}" 
    end 
end 

c = M::C.new("world") 
c.work 
+0

dzięki za wyjaśnienie różnicy między używaniem siebie. i w tym module. –

3

należy poprzedzić metodę moduł self:

module M 
    class C < Struct.new(:param) 
    def work 
     M::helper(param) 
    end 
    end 

    def self.helper(param) 
    puts "hello #{param}" 
    end 
end 
+0

Nie były w pytaniu, ale 'C.work' nazywany jest jako metoda klasy zamiast metody instancji. Czy próbowałeś już nazywać 'M.helper (" foo ")'? – Eimantas

2

C próbuje zadzwonić helper na M gdy helper nie jest w M w klasie singleton. Ponadto nadal powtarzasz, że helper jest funkcją modułu, gdy jest to tylko metoda. Dokonywanie helper funkcją moduł podejmie pracę kodu:

module M 
    class C < Struct.new(:param) 
    def work 
     M::helper(param) 
    end 
    end 

    module_function 

    def helper(param) 
    puts "hello #{param}" 
    end 
end 

tym module w klasie będzie również pracować:

module M 
    class C < Struct.new(:param) 
    include M 

    def work 
     helper(param) 
    end 
    end 

    def helper(param) 
    puts "hello #{param}" 
    end 
end 

W pierwszym przykładzie helper wprowadzanego do M jest jednoelementowy klasie module_function. Drugi przykład importuje metody M do C, dzięki czemu C może z nich korzystać. Kolejna różnica polega na tym, że w pierwszym będziesz mógł zadzwonić pod numer M.helper z dowolnego miejsca w kodzie. W drugim będziesz mógł zadzwonić pod numer helper z dowolnego wystąpienia C w swoim kodzie. Aby rozwiązać ten problem, należy helper private:

module M 
    class C < Struct.new(:param) 
    include M 

    def work 
     helper(param) 
    end 
    end 

    private 
    def helper(param) 
    puts "hello #{param}" 
    end 
end 
1

Oto wyjaśnienie:

Od ruby docs.

Moduł to zbiór metod i stałych. Metody w module mogą być przykładowymi metodami lub metodami modułu. Metody instancji pojawiają się jako metody w klasie, gdy moduł jest włączony, metody modułów nie. Odwrotnie, metody modułów mogą być wywoływane bez tworzenia obiektu enkapsulacji, podczas gdy metody instancji mogą nie być. (Patrz Module # module_function.)

self.methodname wewnątrz moduł tworzy metodę modułu.

W tym przypadku podczas wywoływania M::helper faktycznie robisz M.helper, gdy patrzysz na to z punktu widzenia programisty C++. Odbiornikiem jest moduł Module (instancja modułu typu Ruby Module) w tym przypadku.


Inny sposób, aby patrząc na to, aby zrozumieć koncepcję odbiornika, każde połączenie metoda składa się z odbiornika i metoda nazwie (+ ewentualnie params i bloku kodu). Odbiornikiem może być Module object, Class object lub instancja klasy zdefiniowanej przez użytkownika.

Można wywoływać tylko metody modułu (lub klasy) na obiekcie modułu (lub klasy). Możesz wywołać dowolną metodę (moduł/klasę/instancję) na instancji.

Jeśli chcesz wywołać metodę instancji zdefiniowaną w module, musisz nadać jej odbiornik przez including ten moduł w jakiejś klasie i utworzyć jego instancję.

Więc w tym przypadku Innym rozwiązaniem może być:

module MM 
    def helper(param) 
    puts "hello #{param}" 
    end 

    class ReceiverClass 
    include MM   # add helper() to ReceiverClass 
    end 

    class C < Struct.new(:param) 
    def work 
     ReceiverClass.new.helper(param) 
    end 
    end 
end 

c = MM::C.new("world") 
c.work 
Powiązane problemy