2009-10-04 14 views
5
class A 
    do_something_from_b 

    def method_in_a 
    end 
end 

module B 
    def self.included base 
    base.extend ClassMethods 
    end 

    module ClassMethods 
    def do_something_from_b 
     A.class_eval do 
     alias_method :aliased_method_in_a, :method_in_a 
     end 
    end 
    end 
end 

A.send(:include, B) 

Ten kod nie powiedzie się, ponieważ kiedy do_somethind_from_b jest wywoływana, method_in_a jeszcze nie istnieje.Uruchamianie kodu po klasie jest w pełni załadowany

Więc czy jest jakiś sposób, aby podłączyć do class A po to zostało w pełni załadowany, bez oddanie wezwanie do_something_from_b na koniec class A?

Edycja: Jak wskazano, jest coś nie tak z kodem, ale to nie ma znaczenia. Chcę tylko zilustrować, co chcę osiągnąć, po uruchomieniu kodu po klasa jest zamknięta (nie ma znaczenia, że ​​można ją ponownie otworzyć do woli). A teraz wiem, że to prawdopodobnie niemożliwe.

Dzięki!

+0

Chciałbym zasugerować, aby opublikować działający przykład, z komentarzem "Jak to zrobić, aby praca". W tym przypadku powinna to być tylko jedna linia, ale ten kod wydaje się być łamany na różne sposoby ... – DigitalRoss

+3

Klasy ruby ​​są otwarte, więc nigdy nie ma czasu, kiedy klasa jest w pełni załadowana. –

+0

Sam, dzięki za przypomnienie. Myślę więc, że z tego powodu niemożliwe jest robienie tego, co chciałem. – Ivan

Odpowiedz

5

W języku Ruby klasa nigdy nie jest w pełni załadowana. Możesz go ponownie otworzyć, kiedy tylko chcesz.

class A 
    def method_in_a 
    … 
    end 
end 

Możesz zrobić później, bez względu na to, gdzie jest twój kod (nawet w innym pliku kodu źródłowego).

class A 
    alias :aliased_method_in_a :method_in_a 
end 

czy można zrobić to tak, jak to napisał (która jest dokładnie taka sama jak w poprzednim kodzie)

A.class_eval do 
    alias :aliased_method_in_a :method_in_a 
end 

Jak wskazał A # method_in_a musi istnieć w chwili go alias . Aby upewnić się, że jest to prawdą, można wykonać przed wykonaniem aliasu, aby uzyskać . Jeśli nie wiadomo, kiedy metoda A # method_in_a zostanie utworzony można zrobić

class A 
    def self.method_added(name) 
    alias :aliased_method_in_a :method_in_a if name == :method_in_a 
    end 
end 

A.method_added zostanie automatycznie nazywa ilekroć metoda A zostanie zdefiniowany.

+0

johannes, nie mogę ci wystarczająco podziękować. Ta metoda jest niezwykle przydatna. Podejrzewam, że może to być hit wydajnościowy, ale miejmy nadzieję, że nie będzie zbyt wielki. Przy okazji, nie wiem, co dzieje się z "zwykłym" aliasem, ale używam alias_method_chain Railsów, który wyzwala metodę wypchana w nieskończoną pętlę, więc musiałem użyć zmiennej klasy, aby zobaczyć, czy metoda został już aliasowany. – Ivan

+1

A tu jest trochę więcej informacji na temat method_added: http://blog.sidu.in/2007/12/rubys-methodadded.html – Ivan

+0

Przetestowałem to z prostym aliasem i nie wystąpiło rekursji. – johannes

Powiązane problemy