2009-10-04 5 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) 

Dieser Code wird fehlschlagen, weil, wenn do_somethind_from_b aufgerufen wird, method_in_a noch nicht existiert.Lauf Code nach dem Unterricht ist voll geladen

So ist es eine Möglichkeit, in class A einzuhaken nachdem sie vollständig geladen ist, ohne den do_something_from_b Anruf am Ende class A setzen?

Bearbeiten: Wie bereits erwähnt, gibt es andere Dinge mit dem Code falsch, aber das ist neben dem Punkt. Ich möchte nur illustrieren, was ich erreichen möchte, was Code nach eine Klasse ausgeführt wird (es spielt keine Rolle, dass es nach Belieben wieder geöffnet werden kann). Und jetzt weiß ich, das ist wahrscheinlich nicht möglich.

Danke!

+0

Ich würde vorschlagen, dass Sie ein funktionierendes Beispiel, mit irgendwelchen "wie mache ich diese Arbeit" gebrochenes Zeug auskommentieren. In diesem Fall sollte das nur die eine Zeile sein, aber dieser Code scheint auf verschiedene Arten kaputt zu sein ... – DigitalRoss

+3

Auch Ruby-Klassen sind offen, so dass es nie wirklich einen Zeitpunkt gibt, zu dem eine Klasse vollständig geladen ist. –

+0

Sam, danke für die Erinnerung. Deshalb denke ich, dass es unmöglich ist, das zu tun, was ich wollte. – Ivan

Antwort

5

In Ruby ist eine Klasse nie vollständig geladen. Sie können es jederzeit wieder öffnen.

Sie können später tun, egal wo Ihr Code ist (auch in einer anderen Quellcodedatei).

class A 
    alias :aliased_method_in_a :method_in_a 
end 

oder man könnte es so machen Sie es geschrieben hat (die als dem vorherigen Code genau das gleiche ist)

A.class_eval do 
    alias :aliased_method_in_a :method_in_a 
end 

Wie Sie A # method_in_a wies darauf hin, muss zum Zeitpunkt der Alias ​​existieren es . Um sicherzustellen, dass dies der Fall ist, können Sie auch

require "file_of_class_a" 

tun, bevor Sie den Alias ​​ausführen. Wenn Sie nicht wissen, wenn die Methode A # method_in_a erstellt werden könnten Sie tun

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 wird automatisch aufgerufen, wenn ein Verfahren in A definiert wird.

+0

johannes, ich kann dir nicht genug danken. Diese Methode ist sehr nützlich. Ich vermute, dass es ein Performance-Hit sein kann, aber hoffen wir, dass es nicht zu groß ist. Übrigens, ich weiß nicht, was mit einem "einfachen" Alias ​​passiert, aber ich benutze Rails 'alias_method_chain, die method_added in einer Endlosschleife auslöst, also musste ich eine Klassenvariable verwenden, um zu sehen, ob die Methode war bereits Aliasing. – Ivan

+1

Und hier ist ein bisschen mehr Informationen über method_added: http://blog.sidu.in/2007/12/rubys-methodadded.html – Ivan

+0

Ich testete es mit einfachen Alias, und keine Rekursion aufgetreten. – johannes

Verwandte Themen